title: angular 1.5 component, ui-router resolve, $onChanges lifecycle hook
body: <p>In the following example (<a href="https://plnkr.co/edit/ChxommnERTmaULmVRNY8?p=preview" rel="nofollow noreferrer">plunker</a>), a ui-router state routes to an <em>app</em> component that has a <em>data</em> object and a <em>replace</em> method that replaces this object with a new one using the given value. In its template, it has:</p>
  
  <ul>
  <li>an <em>editor</em> component which triggers the <em>replace</em> method through a callback binding ('&amp;')</li>
  <li>a <em>display</em> component which receives the <em>data</em> object through a 1-way binding ('&lt;'), makes a local copy when the $onChanges lifecycle hook is triggered, and displays the contents of the object</li>
  </ul>
  
  <p>Everything works fine and as expected :-)</p>
  
  <pre class="lang-js prettyprint-override"><code>angular
  .module('app', ['ui.router'])
  
  .config(($urlRouterProvider, $stateProvider) =&gt; {
      $urlRouterProvider.otherwise('/');
  
      $stateProvider
      .state('root', {
        url: '/',
        component: 'app'
    });
  })
  
  .component('app', {
    controller: function () {
      this.data = { name: 'initial' };
      this.replace = (value) =&gt; { this.data = { name: value }; };
    },
    template: `
      &lt;editor on-replace="$ctrl.replace(value)"&gt;&lt;/editor&gt;
      &lt;display data="$ctrl.data"&gt;&lt;/display&gt;
    `
  })
  
  .component('editor', {
    bindings: {
      onReplace: '&amp;'
    },
    controller: function () {
      this.replace = (value) =&gt; this.onReplace({value});
    },
    template: `
      &lt;input type="text" ng-model="value"&gt;
      &lt;button ng-click="$ctrl.replace(value)"&gt; replace object &lt;/button&gt;
    `
  })
  
  .component('display', {
    bindings: {
      data: '&lt;'
    },
    controller: function () {
      this.$onChanges = (changes) =&gt; {
        if (changes.data) {
          this.data = Object.assign({}, this.data);
        }
      };
    },
    template: `
      &lt;p&gt; value : {{ $ctrl.data.name }} &lt;/p&gt;
    `
  });
  </code></pre>
  
  <p>I have a problem with the following second example (<a href="https://plnkr.co/edit/XWtW3fx5VuiTZojcnf63?p=preview" rel="nofollow noreferrer">plunker</a>). It is the exact same setting, except that the <em>app</em> component no longer manages the <em>data</em> itself, but receives a <em>data</em> object through a 1-way binding ('&lt;') that is defined as a resolve of the ui-router state (as can be seen in the comments, I tested both using a global object and method, and interacting through a service). When this resolved object is reassigned, I was expecting the $onChanges hook of the <em>app</em> component to be triggered (as it is for the <em>display</em> component when the data object of the <em>app</em> component is reassigned), but this is not the case. Does anyone has an explanation?</p>
  
  <pre class="lang-js prettyprint-override"><code>let data = { name: 'initial' };
  const replace = (value) =&gt; { data = { name: value }; };
  
  angular
  .module('app', ['ui.router'])
  
  /*.factory('DataService', function () {
    let data = { name: 'initial' };
    return {
      getData: () =&gt; data,
      replace: (value) =&gt; { data = { name: value }; }
    };
  })*/
  
  .config(($urlRouterProvider, $stateProvider) =&gt; {
      $urlRouterProvider.otherwise('/');
  
      $stateProvider
      .state('root', {
        url: '/',
        component: 'app',
        resolve: {
          data: () =&gt; data /*(DataService) =&gt; DataService.getData()*/
        }
    });
  })
  
  .component('app', {
    bindings: {
      data: '&lt;'
    },
    controller: function (/*DataService*/) {
      this.$onChanges = (changes) =&gt; {
        if (changes.data) {
          this.data = Object.assign({}, this.data);
        }
      };
      this.replace = (value) =&gt; { replace(value); }; /*(value) =&gt; { DataService.replace(value); };*/
    },
    template: `
      &lt;editor on-replace="$ctrl.replace(value)"&gt;&lt;/editor&gt;
      &lt;display data="$ctrl.data"&gt;&lt;/consumer&gt;
    `
  })
  
  .component('editor', {
    bindings: {
      onReplace: '&amp;'
    },
    controller: function () {
      this.replace = (value) =&gt; this.onReplace({value});
    },
    template: `
      &lt;input type="text" ng-model="value"&gt;
      &lt;button ng-click="$ctrl.replace(value)"&gt; replace object &lt;/button&gt;
    `
  })
  
  .component('display', {
    bindings: {
      data: '&lt;'
    },
    controller: function () {
      this.$onChanges = (changes) =&gt; {
        if (changes.data) {
          this.data = Object.assign({}, this.data);
        }
      };
    },
    template: `
      &lt;p&gt; value : {{ $ctrl.data.name }} &lt;/p&gt;
    `
  });
  </code></pre>