将属性从一个指令绑定到另一个指令

时间:2016-01-15 11:13:21

标签: javascript angularjs angularjs-directive

我正在尝试在Angular1中使用Angular2中的“组件方法”,我的指令应该相互发送属性。我编写了这样的代码:

父指令

angular
    .module('myModule')
    .controller('parentController', ParentController)
    .directive('parentDirective', () => {
        return {
            restrict: 'E',
            scope: {},
            controller: 'parentController',
            controllerAs: 'ctrl',
            templateUrl: 'parent-template.html'
        }
    });

class ParentController {
    constructor() {
        this._increasableValue = 0;

        setInterval(() => {
            this._increasableValue += 1;
        })
    }

    get increasableValue() { return this._increasableValue; }
}

父 - template.html

<div class="container">
    <child-directive inc="{{ctrl.increasableValue}}"></child-directive>
</div>

儿童指令

angular
    .module('myModule')
    .controller('childController', ChildController)
    .directive('childDirective', () => {
        return {
            restrict: 'E',
            scope: {
                increasableValue: '@inc'
            },
            bindToController: true,
            controller: 'childController',
            controllerAs: 'ctrl',
            templateUrl: 'child-template.html'
        }
    });

class ChildController {
    set increasableValue(value) { this._increasableValue = value; }
    get increasableValue() { return this._increasableValue; }
}

儿童template.html

<div class="container">
    <div>{{ctrl.increasableValue}}</div>
</div>

但是increasableValue冻结了起始值并且根本没有变化。如何从父指令中获取increasableValue并将其绑定到子?

UPD: 这里有jsfiddle来演示问题(也请查看控制台)。

2 个答案:

答案 0 :(得分:1)

似乎龙在setInterval逼近。将其更改为具有ng-click属性的按钮解决了我的问题。此处已更新jsfiddle

如果有人解释问题的根源,我将不胜感激。

答案 1 :(得分:1)

是的你是对的!问题是你如何更新你的变量。

Angular不知道,该值已更改,并且未调用 digest 循环来更新视图。
样本为$inteval service

angular.module('myModule', []);

var ParentController = (() => {
    function ParentController($interval) {
      this._increasableValue = 1;

      var interval = $interval(() => {
        this._increasableValue += 1;
        console.log(this._increasableValue);

        if (this._increasableValue > 20) {
          $interval.cancel(interval);
        }
      }, 1000);
    }

    Object.defineProperty(ParentController.prototype, "increasableValue", {
        get: function () { return this._increasableValue; },
        enumerable: true,
        configurable: true
    });
    
    return ParentController;
})()

var ChildController = (() => {
		function ChildController() {}

    Object.defineProperty(ChildController.prototype, "increasableValue", {
        get: function () { return this._increasableValue; },
        set: function (value) { this._increasableValue = value; },
        enumerable: true,
        configurable: true
    });
    
    return ChildController;
})();

angular
    .module('myModule')
    .controller('parentController', ParentController)
    .directive('parentDirective', () => {
        return {
            restrict: 'E',
            scope: {},
            controller: 'parentController',
            controllerAs: 'ctrl',
            template: `
<div class="container">
		<child-directive inc="ctrl.increasableValue"></child-directive>
</div>`
        }
    });

angular
    .module('myModule')
    .controller('childController', ChildController)
    .directive('childDirective', () => {
        return {
            restrict: 'E',
            scope: {
                increasableValue: '=inc'
            },
            bindToController: true,
            controller: 'childController',
            controllerAs: 'ctrl',
            template: `
<div class="container">
    <div>{{ctrl.increasableValue}}</div>
</div>`
        }
    });
    
angular.bootstrap(document.getElementById('wrapper'), ['myModule'])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<div id="wrapper">
  <parent-directive>Loading...</parent-directive>
</div>

更新:或者您可以像这样简单地调用 $ digest 函数

angular.module('myModule', []);

var ParentController = (() => {
    function ParentController($scope) {
      this._increasableValue = 1;

      var interval = setInterval(() => {
        this._increasableValue += 1;
        console.log(this._increasableValue);
        $scope.$digest();
        if (this._increasableValue > 5) {
          clearInterval(interval);
        }
      }, 1000);
    }

    Object.defineProperty(ParentController.prototype, "increasableValue", {
        get: function () { return this._increasableValue; },
        enumerable: true,
        configurable: true
    });
    
    return ParentController;
})()

var ChildController = (() => {
		function ChildController() {}

    Object.defineProperty(ChildController.prototype, "increasableValue", {
        get: function () { return this._increasableValue; },
        set: function (value) { this._increasableValue = value; },
        enumerable: true,
        configurable: true
    });
    
    return ChildController;
})();

angular
    .module('myModule')
    .controller('parentController', ParentController)
    .directive('parentDirective', () => {
        return {
            restrict: 'E',
            scope: {},
            controller: 'parentController',
            controllerAs: 'ctrl',
            template: `
<div class="container">
		<child-directive inc="ctrl.increasableValue"></child-directive>
</div>`
        }
    });

angular
    .module('myModule')
    .controller('childController', ChildController)
    .directive('childDirective', () => {
        return {
            restrict: 'E',
            scope: {
                increasableValue: '=inc'
            },
            bindToController: true,
            controller: 'childController',
            controllerAs: 'ctrl',
            template: `
<div class="container">
    <div>{{ctrl.increasableValue}}</div>
</div>`
        }
    });
    
angular.bootstrap(document.getElementById('wrapper'), ['myModule'])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<div id="wrapper">
  <parent-directive>Loading...</parent-directive>
</div>