L
L
Lodin2016-01-19 11:22:05
JavaScript
Lodin, 2016-01-19 11:22:05

Why is there a double assignment of an external variable in an Angular directive?

I am writing an AngularJS application with a component approach, where one directive initializes another and passes some data to it. However, when transferring data, the assignment occurs twice (which also leads to problems with two-way binding).
Here is the code:
Module initialization
angular.module('myModule', []);
Parent directive

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

  ParentController.prototype.update = function() {
    this._increasableValue += 1;
  }

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

  return ParentController;
})()

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>
<button ng-click="ctrl.update()">Update</button>`
    }
  });

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

  Object.defineProperty(ChildController.prototype, "increasableValue", {
    get: function() {
      return this._increasableValue;
    },
    set: function(value) {
      this._increasableValue = value;
      console.log(this._increasableValue); // выводит дважды
    },
    enumerable: true,
    configurable: true
  });

  return ChildController;
})();

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>`
    }
  });

Bootstrapping
angular.bootstrap(document.getElementById('wrapper'), ['myModule'])

index.html (partially)
<div id="wrapper">
  <parent-directive>Loading...</parent-directive>
</div>

Why is this overlap happening, and what can be done about it?
Working example on jsfiddle

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey, 2016-01-19
Protko @Fesor

because you use getters and setters, there are some nuances there.
Well, yes, if we enable two-way binding inside the child directive (the child is not very suitable here, our components should be independent as much as possible), then the value will be set only once, at the moment the value is bound to the controller.
Personally, to simplify, I throw a piece of the object inside, and just never change it in the component, but ask the services to do it. Then they will be able to forward the state in a circle.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question