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