Saturday, September 30, 2017

Angular - Add option to select using Jquery

Leave a Comment

I have a directive that adds new options to a select.

For that i'm using:

let opt: any = angular.element(             '<option value="' + opcion.valor + '">' + opcion.texto + '</option>'           );           this.element.append(this.$compile(opt)(scope)); 

I don't want to use templates because I don't want a new scope.

The options get added to the list on the view. But when I select some of them, the ng-model of the select doesn't get updated. It gets value null.

How can I make angular to refresh with the new option values?

Here is a codepen example: Choosing Option X doesn't get reflected on model.

The strange thing is that if i link to angular 1.5.9, it works, but starting with angular 1.6.0 it doesn't.

https://codepen.io/anon/pen/XemqGb?editors=0010

4 Answers

Answers 1

How can i make angular to refresh with the new option values ?

You do not need to do this. Updating model and data binding is done by digest cicle.

Data binding means that when you change something in the view, the scope model automatically updates.

You just need to update your scope and digest cicle is dealing with the rest of work.

I recommend you to not mix jquery with angularJS.

You should definitely try to do things the angular way when possible though.

You should not use jQuery on the top of the AngularJS, because AngularJS digest cycle won't run if we do any angular DOM manipulation or scope variable manipulation using JQuery.

However, you can do this manually using $scope.$apply() method by passing a callback function.

HTML

<select ng-model="selectedValue">   .... </select> 

JS

$('select').change(function(){     var value = $(this).val();     var selectScope = angular.element($("select")).scope();     selectScope.$apply(function(){         selectScope.selectedValue=value;     }); }); 

Answers 2

I want to add new options to the select but without using a new template for the directive

Use compile attribute in directive:

myApp.directive('myList', function() {    return {         restrict: 'EA', //E = element, A = attribute, C = class, M = comment          link: function ($scope, element, attrs) {              // ....         }, //DOM manipulation          compile: function(tElement, tAttrs) {            tElement.append('<option value="10">Option Ten</option>');         }       }   }); 

Updated Demo Codepen


[EDIT 1]

Is possible to do this after a change on external model field ? Watch a field and then add the option ?

Not at all. compile is called once right after we created the instance. This is a phase when Angularjs compiles the directive

However if you want to create value after some delay based on external flow, why do not to use ng-options - You just need to add new value to list of objects and ng-options will do the job for you:

Simple Example Fiddle

$scope.items = [     { value: "C", name: "Process C" },     { value: "Q", name: "Process Q" } ];  $timeout(function(){     $scope.items.push({ value: "New", name: "Process New" });  },3000); 

and HTML:

<select class="form-control" name="theModel" ng-model="theModel"          ng-options="c.value as c.name for c in items">     <option value=""> -- </option>   </select> 

Answers 3

In latest angularJS Select value (read from DOM) is validated

Better to use select's in standard way,

BTW - If you really need this, remove validation by decorating selectDirective as follows

Codepen: https://codepen.io/anon/pen/NapVwN?editors=1010#anon-login

myApp.decorator('selectDirective', function($delegate) {     let originalCtrl = $delegate[0].controller.pop();     $delegate[0].controller.push(function() {       originalCtrl.apply(this, arguments);       this.hasOption = function() {          return true;        }     })     return $delegate; }); 

Answers 4

Actually, what you have failed to understand is data binding. It means that when you have something in the $scope, you have to work with it. So your variable $scope.opcion must be an array as it is a select. The code needs to be something like:

/* AngularJS Basic Directives  For More Examples AngularJS    http://mehmetcanker.com  */  var myApp = angular.module('example', []);  myApp.controller('MyCtrl',['$scope', function($scope) { $scope.opcion = [1]; }])   //This directive doesn't individual scope so  //Controller and Directive share same scope  myApp.directive('myList', function() {    return {         restrict: 'EA', //E = element, A = attribute, C = class, M = comment         link: function ($scope, element, attrs) {           // add options           $scope.opcion.join(2);         } //DOM manipulation     }   }); 

The important part is $scope.opcion = [1] and $scope.opcion.join(value)

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment