最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular directive with two way binding, filter and ng-repeat - Stack Overflow

programmeradmin5浏览0评论

I'm trying to create a directive that accepts an array of objects and run ng-repeat to render them.

app.directive("rockers", function(){
    return {
        restrict : "E",
        replace : true,
        scope : {
            items : '='
        },
        template : '<div>'+
                       '<span ng-repeat="item in items">{{item.name}} Rocks!</span>'+
                    '</div>'

    };
});

In the controller, I set the scope with opjects:

app.controller("appController", function($scope){
    $scope.scopedItems = [{name:"Aanny"}, {name:"Bonny"}, {name:"Danny"}];
});

And then, to call the directive I pass the scopedItems with filter, like this:

<div ng-app="myApp" ng-controller="appController">
    Rockers: 
    <rockers items="scopedItems | filter:{name:'Bonny'}"></rockers>
</div>

Without using the filters in the HTML, everything works fine. When passing the filter I still get the results I want, but I'm also getting this error: "Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!"

What am I doing wrong?

Here is a jsFiddle link to recreate the error.

Thanks!

I'm trying to create a directive that accepts an array of objects and run ng-repeat to render them.

app.directive("rockers", function(){
    return {
        restrict : "E",
        replace : true,
        scope : {
            items : '='
        },
        template : '<div>'+
                       '<span ng-repeat="item in items">{{item.name}} Rocks!</span>'+
                    '</div>'

    };
});

In the controller, I set the scope with opjects:

app.controller("appController", function($scope){
    $scope.scopedItems = [{name:"Aanny"}, {name:"Bonny"}, {name:"Danny"}];
});

And then, to call the directive I pass the scopedItems with filter, like this:

<div ng-app="myApp" ng-controller="appController">
    Rockers: 
    <rockers items="scopedItems | filter:{name:'Bonny'}"></rockers>
</div>

Without using the filters in the HTML, everything works fine. When passing the filter I still get the results I want, but I'm also getting this error: "Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!"

What am I doing wrong?

Here is a jsFiddle link to recreate the error.

Thanks!

Share Improve this question asked Apr 3, 2014 at 9:43 Yair TavorYair Tavor 2,5381 gold badge22 silver badges16 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 3

Also you can pass filtered data to directive like a string:

<rockers items="{{ scopedItems | filter:{name:'Bonny'} }}"></rockers>

and parse it value to object it directive:

app.directive("rockers", function(){
    return {
        restrict : "E",
        replace : true,
        scope : {},
        link:function(scope, elem, attr){
            scope.items = JSON.parse(attr.items);
        },
        template : '<div>'+
                       '<span ng-repeat="item in items">{{item.name}} Rocks!</span>'+
                    '</div>'

    };
});

http://jsfiddle/34ag7/4/

You can pass rocker name into directive by attribute and filter it there:

<div ng-app="myApp" ng-controller="appController">
    Rockers: 
    <rockers name="Bonny" items="scopedItems"></rockers>
</div>

And in directive:

app.directive("rockers", function(){
    return {
        restrict : "E",
        replace : true,
        scope : {
            items : '='
        },
        link:function(scope, elem, attr){
            scope.filteredItems = function(filterItemName){
                return scope.items.filter(function(item){
                    return item.name == filterItemName;
                })
            };
            scope.filteredItem = scope.filteredItems(attr.name);
        },


        template : '<div>'+
                       '<span ng-repeat="item in filteredItem">{{item.name}} Rocks!</span>'+
                    '</div>'

    };
});

http://jsfiddle/b3dc9/39/

You could also use memoization in a custom filter to return the calculated value unless the input value changes.

See this example: Memoizing Angular filters to stop digest errors

I found a very simple solution involving adding another two-way bound scope variable to the directive and filtering inside the directive template instead of inside the html:

<div ng-app="myApp" ng-controller="appController">
    <input type="text" ng-model="find"><br>
    Rockers: 
    <rockers items="scopedItems" filter="find"></rockers>
</div>

Angular gives digest errors when a filtered array expression is passed in as a two-way bound directive scope variable. By using the filter attribute, you can filter anything you type in the input field, or use a $scope object to defined your filter e.g. $scope.find = {name: 'Bonny'}; You could even use a scope filter function or pre-defined filter, anything you would pass into a real filter expression will work because of the two-way binding.

var app = angular.module('myApp', []);

app.controller("appController", function($scope){
    $scope.scopedItems = [{name:"Aanny"}, {name:"Bonny"}, {name:"Danny"}];
});

app.directive("rockers", function($filter){
    return {
        restrict : "E",
        replace : true,
        scope : {
            items : '=',
            filter: '='
        },
        template : '<div>'+
                       '<span ng-repeat="item in items | filter:filter">{{item.name}} Rocks!</span>'+
                    '</div>'
    };
});

Working example: http://jsfiddle/2jhswna6/

发布评论

评论列表(0)

  1. 暂无评论