I have integrated the chosen plugin into my angularjs app. My app.js looks like this.
myApp.directive('chosen', function() {
var linker = function (scope, element, attr) {
scope.$watch('countriesList', function() {
$('#countries').trigger('chosen:updated');
console.log('I acctuallty get in here');
})
element.chosen();
};
return {
restrict: 'A',
link: linker
};
})
my select looks like this
<div class="control-group">
<label for ="countries" class="control-label">Countries: </label>
<div class="controls">
<select chosen ng-model="countries" id="countries" ng-options="country.name for country in countriesList" data-placeholder="Select Countries" multiple class="span chzn-select"></select>
</div>
</div>
The problem is when the page first loads nothing is displayed in the select. The options are there when you inspect element.
The chosen:updated
just doesn't seem to work. I put the console.log()
in the watch and it is firing. If I run the .trigger('chosen:updated')
in the browser it works perfectly. I did try element.trigger
but that did not work either. So Frustrating!
You need to let Angular (well the browser actually) render the select properly before calling chosen
. You can do this by using setTimeout
or Angular's $timeout
.
app.directive('chosen', function($timeout) {
var linker = function(scope, element, attr) {
$timeout(function () {
element.chosen();
}, 0, false);
};
return {
restrict: 'A',
link: linker
};
});
The third argument false
prevents an unnecessary digest loop.
Demo: http://plnkr.co/edit/9Afq65uatTjnb4J6ICcB?p=preview
If you need to add or remove items dynamically this will work:
app.directive('chosen', function($timeout) {
var linker = function(scope, element, attr) {
scope.$watch('countriesList', function() {
$timeout(function() {
element.trigger('chosen:updated');
}, 0, false);
}, true);
$timeout(function() {
element.chosen();
}, 0, false);
};
return {
restrict: 'A',
link: linker
};
});
Demo: http://plnkr.co/edit/rEBu6d3HtaNhThWidB5h?p=preview
Note that by default $watch
uses reference equality to determine if to execute the listener or not. If you add an item to the array the variable countriesList
will still refer to the same array, so the listener will not execute.
The third argument true
passed to $watch
makes it use angular.equals
instead of reference equality.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With