переменная шаблона всегда неопределена ngOnChanges - PullRequest
0 голосов
/ 08 мая 2019

У меня есть дочерний компонент, который используется дважды внутри его родителя, он использует ngOnChages для обновления значений;

Это все работало нормально, но теперь я пытаюсь манипулировать шаблоном внутри дочернего элемента, в соответствии с информацией, передаваемой через @Input переменные.

То, что я нахожу, это; когда родительский компонент загружается впервые, переменные шаблона не определены в вызове функции

Это имеет смысл, поскольку эта функция вызывается в методе onChanges и не дает шаблону достаточно времени для загрузки.

Мне нужно реорганизовать мой код, но как?

На данный момент это работает, если я использую setTimeout

Итак, просто:

@ViewChild('myContainer', {read: ElementRef}) myContainer: ElementRef;
@Input() myUpdatingVar

ngOnChanges(): void {
  if (this.myUpdatingVar === someValue) {
      this.myFunc(this.someValue1);
   } else {
      this.myFunc(this.someValue2);
   }
}

myFunc(param){
   do stuff....
   this.updateDom(anotherParam);
}

updateDom(param) {
// If I use setTimeout this works
this.myContainer.nativeElement.querySelector(`#someId`); // Undefined
}

Ответы [ 4 ]

1 голос
/ 08 мая 2019

Вместо использования ngOnChanges, вы можете обнаружить изменения, используя setter.

Вот что вам нужно сделать

@Input()
set myUpdatingVar(value: any) {
   if(value) {
        this.myFunc(value);
   }
}

Он будет загружаться не только при инициализациипросматривать, но также всякий раз, когда что-то меняется в myUpdatingVar, Angular запускает сеттер и выполняет вашу функцию.Кроме того, ngOnChanges - это дорогой хук жизненного цикла.Если вы не используете его осторожно, он будет запускаться каждый раз, когда что-то изменяется в компоненте.

Но если вы хотите использовать ngOnChanges, вам следует использовать обнаруженные в переменной изменения вместо использования переменнойсам.

Вот пример

ngOnChanges(changes: SimpleChanges): void {
  if (changes.myUpdatingVar.currentValue === someValue) {
      this.myFunc(changes.myUpdatingVar.currentValue);
   } else {
      this.myFunc(changes.myUpdatingVar.currentValue);
   }
}

Вы можете проверить, является ли это первым изменением, а также получить currentValue и previousValue, что полезно в этом случае.

Надеюсь, мой ответ вам как-то помог.Удачного кодирования!

1 голос
/ 08 мая 2019

Ознакомьтесь с этим руководством: https://angular.io/guide/lifecycle-hooks

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

ngAfterViewInit - это ловушка, которая позволяет вам знать, чтоDOM (или, по крайней мере, та абстракция, которую вы видите) готова к запросу.Это означает, что переменные шаблона и viewchildren, среди прочего, не будут работать должным образом до того, как сработает это событие.

РЕДАКТИРОВАТЬ: звучит так, как будто вы понимаете время.Чтобы исправить это, я предлагаю проверить, что переменная шаблона определена перед использованием в onChanges (теперь это будет происходить при всех последующих вызовах onChanges), а затем сделать то же самое в ngAfterViewInit, если вам нужно запустить ее один раз в начале.

0 голосов
/ 08 мая 2019

Как уже говорили, onchanges запускается слишком рано для доступа к viewchildren, вам понадобится что-то вроде этого:

@ViewChild('myContainer', {read: ElementRef}) myContainer: ElementRef;
@Input() myUpdatingVar

ngOnChanges(): void {
  if (this.myContainer) {
    if (this.myUpdatingVar === someValue) {
       this.myFunc(this.someValue1);
     } else {
       this.myFunc(this.someValue2);
     }
   }
}

ngAfterViewInit() {
  this.ngOnChanges();
}

myFunc(param){
   do stuff....
   this.updateDom(anotherParam);
}

updateDom(param) {
// If I use setTimeout this works
this.myContainer.nativeElement.querySelector(`#someId`); // Undefined
}

Таким образом, вы пропускаете логику, если представление не было инициализировано, и вы вручнуювызвать запуск ngOnChanges после инициализации представления.

Все это говорит о том, что, вероятно, существует гораздо более угловатый способ достижения этой цели, если только вы не взаимодействуете с какой-то плохо интегрированной сторонней библиотекой.

0 голосов
/ 08 мая 2019

Для манипулирования DOM вы должны использовать хук жизненного цикла ngAfterViewInit, чтобы убедиться, что шаблон загружен в DOM.

ngOnChanges срабатывает один раз рано, даже раньше ngOnInit.Слишком рано для манипуляций с DOM.

Вы можете использовать логическое значение isViewInitialized и установить для него значение true в ngAfterViewInit, а затем использовать его в состоянии if в ngOnChanges.

...