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.
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.