Angular - Add option to select using Jquery

Viewed 1860

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

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>

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;
});

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)

Related