установка значения свойства после получения данных из API и передачи этих данных дочернему компоненту в Angular

#angular #typescript #api

Вопрос:

В родительском компоненте я получаю данные из API, допустим, это объект с некоторыми свойствами в нем. В полученном объекте «структура» — это свойство, которое я хочу отправить дочернему компоненту, и с помощью этого свойства я добавляю класс к использованию Renderer2, проверяя значение «структуры».

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

Родительский компонент :

 @Component({
  selector: 'dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss']
})

dashboardModel;

loadReport(){
this.ApiService('The-Api-Url',300).subscribe((result)=>{ 
this.dashboardModel = result.dashboardModel;

})
}
///Number 300 is just to show you , it's not important !
 

Родительский HTML-код :

 <dashboard-view 
[dashboardModel]="dashboardModel"
></dashboard-view>

 

Дочерний компонент :

 @Component({
  selector: 'dashboard-view',
  template: `
<div
  #widgetContainer
  class="container"
  id="widget-view">
</div>
`,
  styleUrls: ['./dashboard-view.component.scss']
})
export class DashboardViewComponent implements OnInit {
constructor(private renderer : Renderer2){}
@Input() dashboardModel
@ViewChild ('widgetContainer') widgetContainer :ElementRef
creatStructure(){
this.renderer.addClass(this.widgetContainer.nativeElement , 'container-edit-mode')
}

ngOninit(){
this.creatStructure()
}
}

 

Я пытался вызвать creatStructure() метод в OnInit и AfterViewInit и даже в AfterContentInit, но он всегда говорит, что WidgetContainer не определен.

Пример кода StackBlitz: https://stackblitz.com/edit/angular-ivy-bdpbwx?file=src/app/child/child.component.ts

Комментарии:

1. Используйте ngAfterViewInit вместо ngOnInit

2. @MikeOne Я пытался, но вызов api происходит после установки значения dashboardModel

3. Ваша демонстрационная версия StackBlitz не запускается — в ряде файлов отсутствует импорт и ошибки, не связанные с вашим вопросом:-)

Ответ №1:

Несколько вариантов, которые я мог бы предложить без этого рабочего стека.

  1. Не используйте средство визуализации для установки класса. Установите его в шаблоне с помощью getter; тогда вы не беспокоитесь о просмотре дочерних объектов и порядке инициализации.

Шаблон:

 <div
  #widgetContainer
  class="container"
  [class.container-edit-mode]="isEditMode"
  id="widget-view">
</div>
 

Компонент:

 public get isEditMode(): boolean {
  return this.dashboardModel
    amp;amp; this.dashboardModel.structure
    amp;amp; this.dashboardModel.structure === '12';
}
 

Это защищает от того, что модель панели мониторинга еще не установлена (что является вашей текущей проблемой, поскольку вызов API происходит после инициализации).

  1. Выводите компонент на экран только после получения данных. Спрячьте свой компонент за an *ngIf , чтобы он создавался только после того, как у вас будут данные, тогда вы гарантированно будете this.dashboardModel заполнены ngOnInit вовремя.

Родительский шаблон:

 <ng-container *ngIf="dashboardModel">
  <dashboard-view 
    [dashboardModel]="dashboardModel">
  </dashboard-view>
</ng-container>
 

Примечание: вам все равно нужно разобраться с порядком инициализации дочернего элемента представления, если вы придерживаетесь прямого использования средства визуализации для настройки класса…

  1. Исправьте порядок инициализаций. Как уже упоминалось, если вы собираетесь что-то делать с вашим представлением с помощью средства визуализации, делайте это в / после ngAfterViewInit этапа жизненного цикла. До этого ваш шаблон не существовал, поэтому все ваши дочерние объекты view останутся неопределенными.

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

Компонент:

 @Input() public set dashboardModel(value: DashboardModel) {
  this._dashboardModel = value;
  this.initModel();
}

private initModel(): void {
  if (!this.widgetContainer) console.error(`Hopefully this shouldn't happen`);

  if (this._dashboardModel.structure === '12')
    this.renderer.addClass(this.widgetContainer.nativeElement , 'container-edit-mode');
}