简体   繁体   中英

Watch ng-model in multiple nested ng-repeat

I have the following piece of code

                <div ng-repeat="category in categories">
                <div ng-repeat="(key, value) in category">
                    {{ key + ":"}}
                    <select id={{key}} class="my_select"
                            data-ng-model="key.type"
                            data-ui-select2="{}" multiple>
                        <option ng-repeat="c in value"
                                ng-selected="(filters[key].length>0) && (filters[key].indexOf(c.trim()) !== -1)" >
                            {{c.trim()}}</option>
                    </select>

                </div>
            </div>

and this one in controller, which never activates(console log doesn't display anything when I change selection):

    $scope.$watch('key.type', function(newValue, oldValue){
    console.log("" +newValue + " " + oldValue);
}, true);

How can I watch selects in this scenario? I found numerous answers regarding Angular, ng_repeat and ng_model, but none of them worked for me. Any help is appreciated.

what I'm trying to do: Given categories as [{category : [ laptop, TV]}, {cpu : [ Core i5, Core i7]}] to build two selects and retrieve selected data (select2 with multiple items)

When you use the ng-repeat directive, you create a new scope that is only accessible within the block containing ng-repeat . This block inherits all the scope properties of its parent block.

What this means is that while within the ng-repeat block, you can access the key property, outside it you cannot.

Thus, placing a $watch on it will not work.

What you need to do in this case is to use the ng-change directive which is explicitly meant to respond to changes in the select tag.

Place this directive on the select as:

<div ng-repeat="category in categories">
    <div ng-repeat="(key, value) in category">
        {{ key + ":"}}
        <select id={{key}} class="my_select"
            data-ng-model="key.type"
            data-ui-select2="{}"
            data-ng-change="changeInSelect(key, value)" multiple>
            <option ng-repeat="c in value"
                ng-selected="(filters[key].length>0) && 
                (filters[key].indexOf(c.trim()) !== -1)" >
                    {{c.trim()}}
            </option>
        </select>
    </div>
</div>

and then in your controller, define a function that will handle it:

$scope.changeInSelect = function (key, value) {
    //DO something here
};

The only way that I found was to edit the select2.js that implements select2 in angular.

    $timeout(function () {
      elm.select2(opts);

      // Set initial value - I'm not sure about this but it seems to need to be there
      elm.select2('data', controller.$modelValue);
      elm.on('change', function(a){
          scope.$emit('select2:change', a);
      });

then you can use the followind code to listen in your controller:

    $scope.$on('select2:change', function (event, element) {

    if(element.added){
        console.log(element);
        console.log(event);
        $scope.updateCategories(event.targetScope.key, element.added.text.trim());
    }
    if(element.removed){
        console.log("Removed");
        $scope.cleanUpOldStuff(event.targetScope.key, element.removed.text.trim());
    }
});

Its not the best way, but it works...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM