【问题标题】:How to use ng-repeat in directive with isolate scope?如何在具有隔离范围的指令中使用 ng-repeat?
【发布时间】:2018-11-13 22:11:25
【问题描述】:

我正在尝试在具有隔离范围的指令中使用 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/

作为代码sn-p:

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>

我做错了什么?

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-scope angularjs-ng-repeat


    【解决方案1】:

    这是一个使用隔离作用域的工作示例。

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

    【讨论】:

      【解决方案2】:

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

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

      所以你会这样做:'&lt;li data-ng-repeat="item in items"&gt;'

      您已经通过 scope 属性将项目添加到您的范围:

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

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

      所以你可以用'{{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)属性之一,而不是混合使用它们。

      【讨论】:

      • 传入整个 items 数组和 itemLabelField 有什么意义? itemLabelField 值位于 items 数组中。似乎是多余的。
      • 只要与问题保持一致即可。它在实践中可能具有不同的价值,具体取决于它的使用地点和方式。但是,是的,在这个例子中,最好对它进行硬编码,这样item[itemLabelField] 就变成了item.name
      猜你喜欢
      • 2015-03-17
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      • 2014-12-26
      • 2013-09-04
      • 2014-10-23
      • 1970-01-01
      • 2014-08-07
      相关资源
      最近更新 更多