#angular #viewchild
#angular #viewchild
Вопрос:
У меня проблема с использованием @ViewChild с компонентом, отображаемым через ngIf. Я нашел различные решения, но ни одно из них не пригодилось для меня. Это мой основной компонент, состоящий из различных шагов (я показал только 2 в коде для краткости) с кнопкой для прямой навигации и кнопкой для сброса возврата компонента на первом шаге. Первый шаг показан при открытии страницы:
...
<div class="my-container">
<first-child *ngIf="showFirtChild"></first-child>
<second-child *ngIf="showSecondChild"></second-child>
</div>
<button (click)="goToNextStep()"></button>
<button (click)="reset()"></button>
...
export class MainComponent implements OnInit {
@ViewChild(FirstChild) private firstChildComp: MyFirstChildComponent;
showFirtChild: boolean = true;
ngOnInit() {
//here firstChildComp is defined
}
//code for navigate through steps
reset() {
this.showFirtChild= true;
this.firstChildComp.fillTable(); //fillTable is a function defined in MyFirstChildComponent
}
...
}
Во время навигации по шагам ссылка на firstChildComp теряется, а при вызове reset() результат childComp не определен. Я знаю, что причиной является ngIf, поэтому я попытался использовать ngAfterViewInit:
ngAfterViewInit() {
this.fcomp = this.firstChildComp;
}
reset() {
this.showFirtChild= true;
this.fcomp .fillTable();
}
но это не решает мою проблему.
Есть предложения?
Комментарии:
1. На
ngAfterViewInit
этапе вы можете получить подкомпоненты. ЯвляетсяfillTable
ли метод закрытым?2. Ни один метод не является общедоступным
Ответ №1:
Как говорится в документе Angular:
«Значение True для разрешения результатов запроса до запуска обнаружения изменений. Если какие-либо результаты запроса находятся внутри вложенного представления (например, *ngIf), запрос разрешается после запуска обнаружения изменений «.
Итак, передача параметра { static: false }
в @ViewChild решает проблему, поскольку доступ к нему осуществляется через ngAfterViewInit, вместо этого доступ к on осуществляется { static: true }
до запуска обнаружения изменений so в ngOnInit.
Комментарии:
1. статическая опция доступна только с версии 8 (согласно Angular docs)
Ответ №2:
ngIf удалит ваш компонент из DOM. Таким образом, он становится неопределенным. Если вы используете [hidden]="!showFirstChild"
вместо этого, он будет только скрыт и будет доступен в компоненте.
Вот stackblitz, где вы можете это проверить.
Комментарии:
1. Использование hidden работает правильно, но я предпочитаю использовать пользовательский ngIf, потому что я передаю данные через различные этапы.
2. Хм, тогда я думаю, что решение dince12 идеально.
Ответ №3:
Попробуйте запустить обнаружение изменений между ними, чтобы убедиться, что шаблон DOM считывает DOM после изменения в reset.
В шаблоне:
<first-child #firstChild *ngIf="showFirtChild"></first-child>
В контроллере:
import { ChangeDetectorRef } from '@angular/core';
export class exampleClass implements
{
@ViewChild('firstChild') public firstChildComp: MyFirstChildComponent;
public fcomp: any;
public showFirtChild: boolean;
constructor(private ref: ChangeDetectorRef,
//your services) {}
public ngAfterViewInit()
{
this.showFirtChild = true;
this.ref.detectChanges();
this.fcomp = this.firstChildComp;
}
public reset(): void
{
this.fcomp.fillTable();
}
}
Документация ChangeDetectorRef для дальнейшего чтения.
Комментарии:
1. извините, проверьте редактирование, должно быть хорошо. Если это не работает, пожалуйста, объясните, что не происходит, или какие-либо ошибки.
2. При вашем редактировании fcomp в reset() правильно определен, но ничего не меняется. Это очень странно, похоже, что выполняется fillTable(), фактически никаких ошибок не появляется, но он ничего не делает… Используя отладчик, я вижу, что fcomp верен, и инструкция выполнена, но таблица не заполнена…
3. Итак, вы разобрались с проблемами ViewChild? Не уверен, что я могу помочь с правильным заполнением таблицы. Поместите console.log(); в fillTable(); и если вы видите это, значит, есть проблема с функцией.
4. Это не проблема таблицы, потому что выполняется каждый другой метод MyFirstChildComponent, но на самом деле он ничего не делает.
5. Итак, если бы в MyFirstChildComponent вы запустили this.fillTable(), это сработало бы?
Ответ №4:
Если вы все еще ищете ответ, вы также можете попробовать установить значение статического флага на true . Это приведет к viewContainerRef
загрузке дочернего компонента в зависимости от ngIf
значения.