You must let Angular (well, the browser itself) display the selection correctly before chosen . You can do this using setTimeout or Angular $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 to false prevents an unnecessary digest loop.
Demo: http://plnkr.co/edit/9Afq65uatTjnb4J6ICcB?p=preview
If you need to dynamically add or remove elements, 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 referential equality to determine whether to execute a listener or not. If you add an element to the array, the countriesList variable will still refer to the same array, so the listener will not execute.
The third argument true , passed to $watch , allows angular.equals to be used instead of referential equality.