ng-repeat指令范围

时间:2016-09-19 03:50:27

标签: javascript angularjs

我有一系列重复的项目。在ng-repeat中,有一个需要传递给它的$ index的指令。 指令内的repeaterIndex始终为0,即使该数组中有多个项目。我也试过传递类别而不是$ index,它总是传递给指令的第一个类别。

以下是控制器代码

angular.module('app')
.controller('ImageUploadCtrl', ['$scope', 'fooSvc',
    function ($scope, fooSvc) {
        fooSvc.getCategories().then(function(response){
            $scope.categories = response.data;
        }, function (error) {
            console.log(error);
        });

        $scope.uploadCategoryPhoto = function(categoryIndex){
            //upload photo
        };
    }]);

ng-repeat code

<li ng-repeat="category in categories">
    <my-directive repeater-index="{{$index}}" image-object="category.newFeaturedImageObj" callback="uploadCategoryPhoto"></my-directive>
</li>

myDirective.js

angular.module('app')
.directive('myDirective', [function() {
    return {
        restrict: 'E',
        scope: {
            callback: '=',
            imageObject: '=',
            repeaterIndex: '@'
        },
        templateUrl: 'app/myDirective/myDirective.html',
        link: function(scope) {
            scope.handleFileSelect = function(element) {
                var file = element.files[0];
                var reader = new FileReader();
                reader.onload = function (event) {
                    scope.$apply(function() {
                        scope.imageObject.image = event.target.result;
                        scope.callback(scope.repeaterIndex);
                    });
                };
                reader.readAsDataURL(file);
            };
        }
    };
}]);    

myDirective.html

<div>
    <input id="upload" type="file" accept="image/*"
       onchange="angular.element(this).scope().handleFileSelect(this)"/>
    <label for="upload">
        Upload
    </label>
</div>    

如果我在另一个地方使用该指令并给它一个不同的回调属性,如callback =&#34; fooBar&#34;,该指令仍然会调用uploadCategoryPhoto。它好像页面上的所有指令都采用了第一个指令的属性。

3 个答案:

答案 0 :(得分:0)

您的代码看起来不错。一切都按预期工作。

查看jsfiddle

&#13;
&#13;
angular.module('ExampleApp', [])
  .controller('ExampleController', function($timeout) {
    var me = this;
    $timeout(function() {
      me.categories = [{
        newFeaturedImageObj: {}
      }, {
        newFeaturedImageObj: {}
      }, {
        newFeaturedImageObj: {}
      }];
    }, 5000);

    this.uploadCategoryPhoto = function(categoryIndex) {
      console.log('uploadCategoryPhoto', categoryIndex);
      //upload photo
    };
  })
  .directive('myDirective', [
    function() {
      return {
        restrict: 'E',
        scope: {
          callback: '=',
          imageObject: '=',
          repeaterIndex: '@'
        },
        template: `<div>
    <input id="upload" type="file" accept="image/*"
       onchange="angular.element(this).scope().handleFileSelect(this)"/>
    <label for="upload">
        Upload
    </label>
</div>  `,
        link: function(scope) {
          scope.handleFileSelect = function(element) {
            var file = element.files[0];
            var reader = new FileReader();
            reader.onload = function(event) {
              scope.$apply(function() {
                scope.imageObject.image = event.target.result;
                console.log('repeaterIndex', scope.repeaterIndex);
                scope.callback(scope.repeaterIndex);
              });
            };
            reader.readAsDataURL(file);
          };
        }
      };
    }
  ]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="ExampleApp">
  <div ng-controller="ExampleController as vm">
    Appear after 5 seconds.
    <ul>
      <li ng-repeat="category in vm.categories">
        <my-directive repeater-index="{{$index}}" image-object="category.newFeaturedImageObj" callback="vm.uploadCategoryPhoto"></my-directive>
      </li>
    </ul>
  </div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我相信,您应首先声明“类别”。目前,$ scope.categories正在回调中声明,但到回调代码时,执行DOM已经呈现并且“类别”是mtrx[k][l] = list.begin()[k].begin()[l]; 。如果先声明“类别”并将其分配给数组,则会为“类别”注册观察者,当回调执行并分配数据时,观察者将触发并更新DOM。

undefined

请试一试。

答案 2 :(得分:0)

您在指令模板中使用硬编码ID将输入与标签相关联。 问题是这个ID在ng-repeat中重复出现,并且不再是唯一的。

解决方案是通过在输入元素周围包装label元素来删除ID:

<强> myDirective.html

<div>
    <label>
        Upload
        <input type="file" accept="image/*"
           onchange="angular.element(this).scope().handleFileSelect(this)"/>
    </label>
</div>

或者您可以使用repeater-index参数生成唯一ID:

<强> myDirective.html

<div>
    <input id="upload{{$repeaterIndex}}" type="file" accept="image/*"
       onchange="angular.element(this).scope().handleFileSelect(this)"/>
    <label for="upload{{$repeaterIndex}}">
        Upload
    </label>
</div>