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.
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>'); } } });
[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:
$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)
0 comments:
Post a Comment