Подтвердить что ты не робот

Как подождать привязки в Angular 1,5 компонента (без $scope. $Watch)

Я пишу директиву Angular 1.5, и я сталкиваюсь с неприятной проблемой, пытаясь манипулировать связанными данными до ее существования.

Здесь мой код:

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
      }
     }
    })
}
...

Как вы можете видеть, я делаю вызов AJAX для получения избранных, а затем проверяю его на связанный список форм.

Проблема заключается в том, что обещание выполняется даже до того, как связывание заполняется... так что к моменту запуска цикла ctrl.forms все еще undefined!

Без использования $scope. $watch (который является частью привлекательности 1.5 компонентов), как я могу ждать завершения привязки?

4b9b3361

Ответ 1

Вы можете использовать новые крючки жизненного цикла, в частности $onChanges, чтобы обнаружить первое изменение привязка, вызывая метод isFirstChange. Подробнее об этом здесь.

Вот пример:

<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>

Ответ 2

У меня была аналогичная проблема, я сделал это, чтобы избежать вызова компонента до тех пор, пока значение, которое я собираюсь отправить, не будет готово:

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

Ответ 3

Оригинальный плакат сказал:

обещание выполняется еще до того, как переплет заселен... sot hat к моменту запуска цикла, ctrl.forms по-прежнему undefined

Начиная с AngularJS 1.5.3, мы привязки жизненного цикла и чтобы удовлетворить вопрос OP, вам просто нужно переместить код, который зависит на привязках, выполняемых внутри $onInit():

$onInit() - вызывается на каждом контроллере после того, как все контроллеры на были построены и были инициализированы их привязки (и перед функциями предварительной и последующей ссылки для директив по этому элемент). Это хорошее место для ввода кода инициализации для вашего контроллер.

Итак, в примере:

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

Так что да, есть $onChanges(changesObj), но $onInit() конкретно обращается к исходному вопросу о том, когда мы можем получить гарантию того, что привязки были разрешены.

Ответ 4

У меня была аналогичная проблема, и я нашел эту статью очень полезной. http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html

У меня есть вызов ajax, который попадает на сервер при загрузке страницы, и моему компоненту необходимо вернуть возвращаемое значение ajax для правильной загрузки. Я реализовал его следующим образом:

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

Теперь мой компонент работает отлично. Для справки я использую Angular 1.5.6