简体   繁体   中英

How to use ng-repeat in directive with isolate scope?

I'm trying to use ng-repeat in a directive that has an isolate scope, but I can't seem to get it working.

When I add an isolate scope to my directive, ng-repeat seems to not be able to see items , which I understand.

However, even if I use the = isolate scope, I get the error message:

Error: Syntax Error: Token 'Object' is unexpected, expecting []] at column 9 of the expression [[object Object],[object Object],[object Object]] starting at [Object],[object Object],[object Object]].

Here is a jsFiddle of ng-repeat working in a directive with no isolate scope:

http://jsfiddle.net/urlology/DA47k/3/

And using a = isolate scope:

http://jsfiddle.net/urlology/CL4AT/11/

As a code snippet:

 var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.open = false; $scope.items = [{ name: 'A', value: 1 }, { name: 'B', value: 2 }, { name: 'C', value: 3 } ]; }); app.directive('myDirective', ['$compile', function($compile) { return { restrict: 'A', link: function(scope, element, attrs) { var items = attrs.items; console.log('items %o', items); var itemLabelField = attrs.itemLabelField var template = '<ul>' + '<li data-ng-repeat="item in ' + items + '">' + '{{item.' + itemLabelField + '}}' + '</li>' + '</ul>'; // Render the template. element.html('').append($compile(template)(scope)); } } }]); 
 <html ng-app="myApp"> <head> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script> </head> <body ng-controller="myCtrl"> <div my-directive items="items" item-label-field="name"></div> </body> </html> 

What am I doing wrong?

Here is a working example using the isolated scope.

http://jsfiddle.net/DA47k/6/

You only need to pass in the object to the isolated scope with '=' and then you can access its properties in your template with dot notation instead of passing them in a new attribute.

app.directive('myDirective', ['$compile', function($compile) {
return {
    restrict: 'A',
    scope: {
        items: '='
    },    
    link: function(scope, element, attrs) {

        var template =
            '<ul>' +
                '<li data-ng-repeat="item in items">' +
                    '{{item.name}}' +
                '</li>' +
            '</ul>';

        // Render the template.
        element.html('').append($compile(template)(scope));
    }
}
}]);

Looks like it's complaining about your template.

By doing '<li data-ng-repeat="item in ' + scope.items + '">' you are in fact converting scope.items to a string. You don't want that, you want it to go through the items in your items array.

So you would do: '<li data-ng-repeat="item in items">'

You've already added items to your scope through the scope property:

scope: {
    items: "=",
    itemLabelField: "@" //read below
}

That's enough to fix your problem, but as you can tell, I've also added itemLabelField so you don't need to use var itemLabelField = attrs.itemLabelField . The @ binder binds by value rather than the parent's scope.

So instead of '{{item.' + itemLabelField + '}}' '{{item.' + itemLabelField + '}}' you can do '{{item[itemLabelField]}}' .

Now you'll find your link function only has a plain string template with a compile. Ideally you'd use a template property instead of manually inserting code inside the element.

template:
    '<ul>' +
        '<li ng-repeat="item in items">' +
        '{{item[itemLabelField]}}' +
        '</li>' +
    '</ul>'

You could even put it in a seperate file and use the templateUrl property.

Here's the full changed code: http://jsfiddle.net/DA47k/12/

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

app.controller('myCtrl', function ($scope) {
    $scope.open = false;

    $scope.items = [
        { name: 'A', value: 1 },
        { name: 'B', value: 2 },
        { name: 'C', value: 3 }
    ];
});

app.directive('myDirective', function() {
    return {
        restrict: 'A',
        scope: {
            items: "=",
            itemLabelField: "@"
        },
        template:
            '<ul>' +
                '<li ng-repeat="item in items">' +
                    '{{item[itemLabelField]}}' +
                '</li>' +
            '</ul>'
    }
});

And just to add, for consistency use either one of ng-xxxx or data-ng-xxxx (or ng:xxxx) attributes rather than mixing them.

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