为什么双向绑定不更新指令控制器

时间:2014-11-06 01:34:09

标签: angularjs angularjs-directive angularjs-scope

符合John Papa的style guide我更新了我的指令以使用ControllerAs语法。但是,在执行此操作后,我的指令在对指令绑定的变量进行更改时不会更新。

即。当mainCtrl.rules更新时,ctrl.rules的值不会更新

要解决这个问题,我必须在链接函数中创建一个监视,当$ scope.rules更改时更新ctrl.rules变量。

为什么这是 - 指令和控制器不在同一范围内?

HTML

<div my-directive rules="mainCtrl.rules"></div>

JS - 主Ctrl

rulesService.get().then(mainCtrl.rules = response.rules;);

JS - 指令

(function () {

    angular.module('myModule')
        .directive('myDirective', myDirective);

        myDirective.$inject = [];

        function myDirective()
        {
            var directive = {
                restrict: 'A',
                scope: {
                    rules: '='
                },
                controller: 'myCtrl',
                controllerAs: 'ctrl',
                templateUrl: "/Template/myDirective",
                transclude: true,
                link: linkFunc
            };

            return directive;
        };

        angular.module('myModule')
            .controller('myCtrl', myCtrl);

        myCtrl.$inject = ['$scope'];

        function myCtrl($scope)
        {
            var ctrl = this;
            ctrl.rules = $scope.rules;
            ctrl.showRules = false;
            ctrl.toggleShowRules = toggleShowRules;

            function toggleShowRules() {
                ctrl.showRules = !ctrl.showRules;
            };
        };

        function linkFunc($scope, $element, $attrs, ctrl)
        {
            //watch the rules collection on the directive and update controller if it changes
            $scope.$watch("rules", function (newValue, oldValue) {
                if(newValue != oldValue)
                {
                    ctrl.rules = newValue;
                }
            });
        };
})();

TEMPLATE

   <div class="rules" ng-show="rules.length > 0">
        <ul ng-show="ctrl.showRules">
            <li ng-repeat="rule in ctrl.rules" class="rule-details">
                <p>{{rule.title}}</p>                               
            </li>
        </ul>
    </div>

2 个答案:

答案 0 :(得分:0)

您的链接函数$scope不是提供者,它是指令的隔离scope,所以我认为你所拥有的是一个ctrl,其中this不是指令,但它是构造函数。

我认为如果你做这样的事情,你会看到差异。

function myCtrl($scope, $attrs, $log) {

   this.scope = $scope;

   $log.debug(this);
   // vs
   $log.debug(this.scope);

答案 1 :(得分:0)

ctrl.rules = $scope.rules;中,有问题的代码是myCtrl,这将指向现有的规则列表。然后,当rulesService.get().then(mainCtrl.rules = response.rules;);出现时,它会将指令中的$scope.rules设置为指向新数据,但ctrl.rules仍然指向旧列表。有两种方法可以在不对代码进行重大更改的情况下解决此问题。

选项1 :您可以更新mainCtrl,而不是替换mainCtrl.rules.length = 0; angular.extend(mainCtrl.rules, response.rules); 中的引用:

ctrl.rules

该选项虽然有点昂贵,但因为存在循环涉及使用新值更新参考。

选项2 :您可以创建一个返回$scope.rules而不是$scope.rules您的函数,而不是将ctrl.rules = $scope.rules设置为引用ctrl.getRules = function () { return $scope.rules; } 可以做到以下几点:

ng-repeat

然后在您的模板中将<li ng-repeat="rule in ctrl.getRules()" class="rule-details"> 更改为

{{1}}

选项2有点容易理解,而选项1对于那些试图阅读代码的人更难理解。