如何在具有隔离作用域的指令中使用 ng-repeat

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

本文关键字:指令 ng-repeat 作用域 隔离      更新时间:2023-09-26

我正在尝试在具有隔离范围的指令中使用ng-repeat,但我似乎无法使其工作。

当我在我的指令中添加隔离范围时,ng-repeat似乎无法看到items,我理解这一点。

但是,即使我使用 = 隔离范围,也会收到错误消息:

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

下面是一个 ng-repeat 的 jsFiddle 在一个没有隔离作用域的指令中工作:

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

并使用=隔离范围:

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

作为代码片段:

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>

我做错了什么?

下面是一个使用隔离范围的工作示例。

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

您只需使用"="将对象传递到隔离范围,然后就可以在模板中使用点表示法访问其属性,而不是在新属性中传递它们。

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));
    }
}
}]);

看起来它在抱怨您的模板。

通过执行'<li data-ng-repeat="item in ' + scope.items + '">'您实际上是将scope.items转换为字符串。你不希望这样,你希望它遍历你的项目数组中的项目。

所以你会做:'<li data-ng-repeat="item in items">'

你已通过 scope 属性将项添加到范围:

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

这足以解决您的问题,但正如您所知,我还添加了itemLabelField,因此您无需使用var itemLabelField = attrs.itemLabelField。@ 绑定程序按值而不是父级的范围绑定。

因此,您可以'{{item[itemLabelField]}}'而不是'{{item.' + itemLabelField + '}}'.

现在你会发现你的链接函数只有一个带有编译的纯字符串模板。理想情况下,应使用模板属性,而不是在元素中手动插入代码。

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

您甚至可以将其放在单独的文件中并使用 templateUrl 属性。

以下是完整更改的代码: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>'
    }
});
补充一点,为了保持一致性,请使用ng-xxxx或

data-ng-xxxx(或ng:xxxx)属性之一,而不是混合它们。