【问题标题】:AngularJs: Why does scope inside my directive not update when async data arrives?AngularJs:为什么异步数据到达时我的指令内的范围不更新?
【发布时间】:2015-01-12 11:32:05
【问题描述】:

我有一个具有隔离作用域的指令,它通过引用获取一个作用域变量

angular.module('myApp')
    .directive('myDirective', function() {
        return {
            scope: {
                items: '='
            },
            templateUrl: 'template.html',
            replace: true,
            controller: 'myDirectiveCtrl',
            controllerAs: 'ctrl'
        };
    })
    .controller('myDirectiveCtrl', function($scope) {
        this.items = $scope.items;
    });

这是这样传入的:

    <div my-directive items='items'></div>

在外部控制器中异步加载数据并更新传递给指令的范围项:

angular.module('myApp', [])
  .controller('myCtrl', function($scope) {

    $scope.setItems = function() {
      $scope.items = [
        'Here',
        'There',
        'Everywhere'
      ];
    };
  });

加载数据时,我的指令之外的范围会更新,但内部不会更新

我的html:

      <div my-directive items='items'></div> <!-- this doesn't update --> 

      Outside directive
      <ul ng-repeat='i in items'>            <!-- this does update -->
        <li>{{i}}</lu>
      </ul>

      <button ng-click="setItems()">Set items</button>

如何在我的指令中获取我的范围以进行更新?我要吗

Plunker here

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    当 Angular 第一次运行你的指令的控制器函数时,你的 $scope.items === undefined,所以当你运行 this.items = $scope.items 时,你的 this.items === undefined 也是。

    就是这样。之后没有任何变化this.items

    这与$scope.items 不同。 $scope.items 是双向绑定到外部作用域的,因此每当 Angular 检测到外部变化时,它都会设置隔离作用域变量。

    最简单的方法(在我看来也是最合适的)是直接在指令中使用$scope 属性:

    <div>
        Inside directive
        <ul ng-repeat="i in items">
          <li>{{ i }}</li>
        </ul>
    </div>
    

    如果您想将控制器用作 ViewModel 而不是范围(我不知道您为什么会这样做),您可以这样做:

    $scope.$watchCollection("items", function(newVal, oldVal) {
       ctrl.items = newVal;
    });
    

    编辑:

    在 Angular 1.3 中,您还可以在指令的定义中执行 bindToController: true,以便控制器属性“items”将获得 $scope.items 获得的双向绑定。然后,你甚至不需要做this.items = $scope.items;

    您的forked plunker 来说明。

    【讨论】:

    • 谢谢。控制器的使用受到这篇博文的影响:teropa.info/blog/2014/10/24/…
    • 我没有说你不应该使用控制器。我的意思是,范围暴露的变量不需要分配给控制器的变量。
    • @SteveLorimer,我用bindToController 的另一种方法编辑了答案,以使您的示例有效
    • 不知道bindToController - 太棒了 - 谢谢!
    • 我想如果我们不更改提供给指令的数据中的任何内容,这将起作用。但是,如果我在指令控制器中更新它怎么办?那么我将如何捕捉更新事件?这是我正在谈论的plunker
    【解决方案2】:

    如果它是隔离范围,则在指令控制器中创建单独的变量后,您将无法更改指令中的内容。

    Here 是更新后的 plunker,它删除了指令的控制器。

    'use strict';
    
    angular.module('myApp')
        .directive('myDirective', function() {
            return {
                scope: {
                    items: '='
                },
                templateUrl: 'template.html',
                replace: true
            };
        });
    

    【讨论】:

      【解决方案3】:

      尝试将您的物品放入一个对象中。 See this example at Plunker

      index.html

      <div my-directive items='allItems'></div>
      
        Outside directive
        <ul ng-repeat='i in allItems.items'>
          <li>{{i}}</lu>
        </ul>
      
        <button ng-click="setItems()">Set items</button>
      </div>
      

      directive.js:

      'use strict';
      
      angular.module('myApp')
      .directive('myDirective', function() {
        return {
          scope: {
            items: '='
          },
          templateUrl: 'template.html',
          replace: true,
          controller: 'myDirectiveCtrl',
          controllerAs: 'ctrl'
        };
      })
      .controller('myDirectiveCtrl', function($scope) {
          this.items = $scope.items;
      });
      

      template.html:

      <div>
        Inside directive
        <ul ng-repeat="i in ctrl.items.items">
          <li>{{ i }}</li>
        </ul
      </div>
      

      script.js:

      angular.module('myApp', [])
      .controller('myCtrl', function($scope) {
        $scope.allItems={};
        $scope.setItems = function() {
          $scope.allItems.items = [
            'Here',
            'There',
            'Everywhere'
          ];
        };
      });
      

      这里有更好的解释:

      Angular - ngModel not updating when called inside ngInclude

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-06
        • 2012-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多