简体   繁体   中英

How to wait for binding in Angular 1.5 component (without $scope.$watch)

I'm writing an Angular 1.5 directive and I'm running into an obnoxious issue with trying to manipulate bound data before it exists.

Here's my code:

app.component('formSelector', {
  bindings: {
    forms: '='
  },
  controller: function(FormSvc) {

    var ctrl = this
    this.favorites = []

    FormSvc.GetFavorites()
    .then(function(results) {
    ctrl.favorites = results
    for (var i = 0; i < ctrl.favorites.length; i++) {
      for (var j = 0; j < ctrl.forms.length; j++) {
          if (ctrl.favorites[i].id == ctrl.newForms[j].id) ctrl.forms[j].favorite = true
      }
     }
    })
}
...

As you can see, I'm making an AJAX call to get favorites and then checking it against my bound list of forms.

The problem is, the promise is being fulfilled even before the binding is populated... so that by the time I run the loop, ctrl.forms is still undefined!

Without using a $scope.$watch (which is part of the appeal of 1.5 components) how do I wait for the binding to be completed?

我有一个类似的问题,我这样做是为了避免调用组件,直到我要发送的值准备就绪:

<form-selector ng-if="asyncValue" forms="asyncValue" ></form-selector>

You could use the new lifecycle hooks , specifically $onChanges , to detect the first change of a binding by calling the isFirstChange method. Read more about this here .

Here's an example:

 <div ng-app="app" ng-controller="MyCtrl as $ctrl"> <my-component binding="$ctrl.binding"></my-component> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js"></script> <script> angular .module('app', []) .controller('MyCtrl', function($timeout) { $timeout(() => { this.binding = 'first value'; }, 750); $timeout(() => { this.binding = 'second value'; }, 1500); }) .component('myComponent', { bindings: { binding: '<' }, controller: function() { // Use es6 destructuring to extract exactly what we need this.$onChanges = function({binding}) { if (angular.isDefined(binding)) { console.log({ currentValue: binding.currentValue, isFirstChange: binding.isFirstChange() }); } } } }); </script> 

The original poster said :

the promise is being fulfilled even before the binding is populated... sot hat by the time I run the loop, ctrl.forms is still undefined

Ever since AngularJS 1.5.3, we have lifecycle hooks and to satisfy the OP's question, you just need to move the code that is depending on the bindings being satisfied inside $onInit() :

$onInit() - Called on each controller after all the controllers on an element have been constructed and had their bindings initialized (and before the pre & post linking functions for the directives on this element). This is a good place to put initialization code for your controller.

So in the example:

app.component('formSelector', {
  bindings: {
    forms: '='
  },
  controller: function(FormSvc) {
    var ctrl = this;
    this.favorites = [];

    this.$onInit = function() {
      // At this point, bindings have been resolved.
      FormSvc
          .GetFavorites()
          .then(function(results) {
            ctrl.favorites = results;
            for (var i = 0; i < ctrl.favorites.length; i++) {
              for (var j = 0; j < ctrl.forms.length; j++) {
                if (ctrl.favorites[i].id == ctrl.newForms[j].id) {
                  ctrl.forms[j].favorite = true;
                }
              }
            }
          });
    }
}

So yes there is a $onChanges(changesObj) , but $onInit() specifically addresses the original question of when can we get a guarantee that bindings have been resolved.

I had a similar problem and I found this article very helpful. http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html

I have an ajax call that hits the server on page load and my component needs the ajax return value to properly load. I implemented it this way:

this.$onChanges = function (newObj) {
      if (newObj.returnValFromAJAX)
        this.returnValFromAJAX = newObj.returnValFromAJAX;
    };

Now my component works perfectly. For reference I am using Angular 1.5.6

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM