AngularJs:为什么异步数据到达时我的指令中的范围不会更新?

时间:2014-11-14 23:52:26

标签: angularjs angularjs-directive angularjs-scope

我有一个带隔离范围的指令,它通过引用

获取范围变量
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

3 个答案:

答案 0 :(得分:5)

当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来说明。

答案 1 :(得分:3)

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

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

'use strict';

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

答案 2 :(得分:1)

尝试将物品放入物品中。 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