1

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.

Kunal Kapadia
  • 3,223
  • 2
  • 28
  • 36

2 Answers2

0

Try the following:

  1. use $observe instead of $watch. Follow this link to know why.
  2. use the following 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>

Community
  • 1
  • 1
Nicolai
  • 1,907
  • 1
  • 23
  • 31
  • The link says "Use $observe when you need to observe/watch a DOM attribute that contains interpolation (i.e., {{}}'s)" Here in my HTML, i am not using interpolation, then why do i need to use $observe. And why is $watch not getting fired? Please let me know if i am missing something. – Kunal Kapadia Aug 12 '14 at 18:04
0

This worked for me.

Directive:

directive('chosen', function ($timeout) {
    var linker = function (scope, element, attrs) {

        scope.$watch('chosenModelList', function (value) {
            element.trigger('chosen:updated');
        });

        scope.$watch('chosenModel', function (value) {
            element.trigger('chosen:updated');
        });

        element.chosen({
            display_selected_options: false,
            max_selected_options: scope.maxSelectedOptions || 3,
            disable_search_threshold: 1000
        });
    };

    return {
        restrict: 'A',
        scope: {
            'chosenModelList': '=',
            'chosenModel': '=',
            'maxSelectedOptions': '='
        },
        link: linker
    };
})

HTML:

<select class="form-control" id="BusinessLocations" name="businessLocations" data-placeholder="Select one or more location"
    chosen
    chosen-model-list="businessLocations"
    chosen-model="listing.locations"
    max-selected-options="1000"
    multiple=""
    data-ng-model="listing.locations"
    required ng-focus
    data-ng-options="businessLocation.id as businessLocation.address for businessLocation in businessLocations"></select>
Kunal Kapadia
  • 3,223
  • 2
  • 28
  • 36