可能的Angular属性指令错误?

时间:2016-11-09 12:43:35

标签: javascript angularjs angularjs-directive

我试图创建一个Angular指令,它只是一个HTML属性(my-directive)。该指令使用一些输入属性(textlength)。

<li my-directive text="first" length="6"></li>

当我只使用一次时,一切都很好用。但我想多次使用它,列表项目:

<ul>
  <li my-directive text="first" length="elements[0].len"></li>
  <li my-directive text="second" length="elements[1].len"></li>
  <li my-directive text="third" length="elements[2].len"></li>
  <li my-directive text="fourth" length="elements[3].len"></li>
</ul>

这是我遇到一种奇怪的行为时:每个列表项都会显示最后一项的属性。我查了一下,指令控制器收到不同的值。但是,只显示最后一个。

我很确定其他人之前碰过这个,但我找不到任何相关内容。

Plunkr here

更新

看起来这个问题可以使用ng-repeat解决,但我不想使用它。对我来说,它看起来仍然是一个错误。

3 个答案:

答案 0 :(得分:4)

使用隔离范围指令将解决问题

http://plnkr.co/edit/pwfbShFYLPMHlSLf48ng?p=preview

.directive('myDirective', function () {
    return {
      restrict: 'A',
      bindToController: {
        // text: '@text',
        length: '='
      },
      scope: {},
      controller: function() {
        var ctrl = this;
        return ctrl;
      },
      controllerAs: 'ctrl',
      template: '{{ ctrl.text }} - {{ ctrl.length }}'
    }
  });

答案 1 :(得分:2)

我个人认为它可以被解释为一个错误,但老实说更像是bindToController和指令工作的结果。

问题可以描述为范围问题。默认情况下,指令不会创建隔离范围,除非您告知它这样做。根据{{​​3}}使用bindToController默认情况下也不会创建一个作用域,所以你的所有指令都是通过逻辑事故来做的,就是在父作用域上绑定你的控制器作用域(即myController) 。例如,如果在链接函数上添加console.log(scope),您将看到每个指令的所有范围都相同。

  link: function (scope) { console.log(scope);}

但是,如果在不知道此行为的情况下处理此问题可能会有问题,可以通过创建一个隔离的范围(如以下示例)并使用布尔版本的bindToController功能来完成。

  bindToController: true,
  scope: {
    text: '@text',
    length: '='
  }

完整代码段:

&#13;
&#13;
  angular.module('myApp', [])
    .controller('myController', function($scope) {
      $scope.test = 'here';
      $scope.elements = [{
        len: 7
      }, {
        len: 13
      }, {
        len: 12
      }, {
        len: 35
      }, ]
    })
    .directive('myDirective', function() {
      return {
        restrict: 'A',
        bindToController: true,
        scope: {
          text: '@text',
          length: '='
        },
        controller: function() {
          var ctrl = this;
          return ctrl;
        },
        controllerAs: 'ctrl',
        template: '{{ ctrl.text }} - {{ ctrl.length }}'
      }
    });

  angular.element(document).ready(function() {
    angular.bootstrap(document, ['myApp']);
  });
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-controller="myController">
  {{ test }}
  <br>
  <ul>
    <li my-directive text="first" length="elements[0].len"></li>
    <li my-directive text="second" length="elements[1].len"></li>
    <li my-directive text="third" length="elements[2].len"></li>
    <li my-directive text="fourth" length="elements[3].len"></li>
  </ul>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

这可能是一个解决方案。

<body ng-app="myApp">
    <div ng-controller="myController">
      {{ test }}
      <ul>
        <li ng-repeat="elm in elements" my-directive text="{{elm.text}}" length="elm.len"></li>
      </ul>
    </div>
  </body>

和script.js

$scope.elements = [
         {
           text:'first',
           len: 7
         },
         {
           text:'second',
           len: 13
         },
         {
           text:'third',
           len: 12
         },
         {
           text:'fourth',
           len: 35
         },
      ]