This is my directive:
    directive('chosen', function ($timeout, $rootScope) {
        var linker = function (scope, element, attrs) {
            scope.$watch('chosenModelList', function () {
                element.trigger('chosen:updated');
                console.log('chosen:updated');
                $timeout(function() {
                    element.trigger('chosen:updated');
                }, 100);
                if (!$rootScope.$$phase)
                    $rootScope.$apply();
            }, true);
            scope.$watch('chosenModel', function () {
                element.trigger('chosen:updated');
                $timeout(function () {
                    element.trigger('chosen:updated');
                }, 100);
                if (!$rootScope.$$phase)
                    $rootScope.$apply();
            }, true);
            element.chosen({
                display_selected_options: false,
                max_selected_options: "3",
                disable_search_threshold: 1000
            });
        };
        return {
            restrict: 'A',
            scope: {
                'chosenModelList': '=',
                'chosenModel': '='
            },
            link: linker
        };
    })
here is how i use it in HTML:
                <select class="form-control" id="BusinessLocations" name="businessLocations" **chosen chosen-model-list="businessLocations"** multiple="" data-placeholder="Select one or more location"
                        data-ng-model="listing.locations"
                        required ng-focus
                        data-ng-options="businessLocation.id as businessLocation.address for businessLocation in businessLocations"></select>
Model is getting updated in this way in controller:
                $scope.listing.businessOwner = $scope.$parent.businessId;
                if (!modifying) {
                    $scope.getLocations($scope.listing.businessOwner).then(function (locations) {
                        **$scope.businessLocations = locations;**
                        console.log('businesLocations');
                        if (locations.length === 1) {
                            $scope.listing.locations = [$scope.businessLocations[0].id];
                        }
                    });
                    mixpanelService.track('Listing Create Form');
                } else {
                    listingService.getListings({ 'id': $location.search().id, 'includeLocations': true, 'includeBusiness': true }).then(function (listings) {
                        $scope.getLocations(listings[0].businessOwnerId).then(function (locations) {
                            **$scope.businessLocations = locations;**
                            console.log('businesLocations');
                            $scope.listing = listings[0];
                            $scope.listing.businessOwner = $scope.listing.businessOwnerId;
                            var locationIds = [];
                            for (var i = 0; i < $scope.listing.locations.length; i++) {
                                locationIds.push($scope.listing.locations[i].id);
                            }
                            $scope.listing.locations = locationIds;
                        });
                    });
                    mixpanelService.track('Listing Edit Form');
                }
watch is not getting triggered as businessLocations model is updated. Same directive is working in some other part of the code, where i have used it in the same way.
Although passing true as third parameter of $watch was not required, i just tried if that would work, but no success. $rootScope.$apply() is also there for the same reason.
 
     
    