Невозможно получить доступ к вложенному объекту после обновления Angular 8 - PullRequest
0 голосов
/ 28 октября 2019

У меня было приложение Angular 2 и я решил обновить его до Angular 8 (ранее не работал ни с чем более новым, чем 2).

В одном случае у меня есть компонент диалога с динамически загруженным компонентом внутреннего содержимого, но компонент содержимого не получает присвоенные ему переменные. Ранее они были доступны на ngOnInit, не говоря уже о ngAfterViewInit, но теперь их нет.

Вот пример кода для конечного объекта (компонента содержимого):

public params: ContentParams;
public isDataValid = true;
public error = '';

constructor() {
}

ngAfterViewInit() {
    const o = this;
    const t = setTimeout(function() {
        console.log(o.params); // works
    }, 500);
    console.log(this.params); // undefined
}

А вот родительское создание (компонент диалога) + назначение параметров компоненту контента:

ngAfterViewInit(): void {
    const factory = this._componentResolver.resolveComponentFactory(this.contentComponentType);
    this._dialogContentComponent = this.contentContainerRef.createComponent(factory).instance as IDialogContentComponent<any, any>;
    this._changeDetectorRef.detectChanges(); // necessary change for the dialog component to appear

    if (this._dialogConfig.contentParams) {
        this._dialogContentComponent.params = this._dialogConfig.contentParams;
    }
}

Есть ли другое событие жизненного цикла в компоненте контента, на которое мне нужно подписаться? Или это просто неправильный способ работы в новых версиях Angular?

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Для таких сценариев я предпочитаю использовать темы

Добавить тему в одну общую службу, а затем разделить состояние между вашими компонентами или службами.

Общая служба

@Injectable()
export class SharedService {

  public params$: Subject<any> = new Subject();

  constructor() { }

}

Обновление


constructor(private _sharedService: SharedService) {
    this._sharedService.params$.next({test: 1})
}

Подписаться

import { Component, OnInit, AfterViewInit } from '@angular/core';
import { Subject } from 'rxjs';
import { SharedService } from './shared.service';


interface ContentParams {}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {

  public params: ContentParams;
  public isDataValid = true;
  public error = '';

  constructor(private _sharedService: SharedService) {

  }

  ngOnInit() {
    this._sharedService.params$.subscribe( params => {
      console.log(params) // {test: 1}
      this.params = params;
    });
  }

}


1 голос
/ 28 октября 2019

Ваш AfterViewInit () сработает, когда завершится выполнение этой ссылки, поэтому к моменту ее вызова у вас не будет загружено params . Вот почему setTimeout () работает.

this._dialogContentComponent = this.contentContainerRef.createComponent(factory).instance as IDialogContentComponent<any, any>;

Вы можете использовать всю мощь RxJS, чтобы помочь (не забывайте отписываться):

import { Subject } from 'rxjs';

export class Something {
    public params: ContentParams;
    public isDataValid = true;
    public error = '';
    public params$ = new Subject();

    constructor() {
        this.params$.subscribe((value) => {
            this.params = value;
        });
    }

    ngAfterViewInit() {
        const o = this;
        const t = setTimeout(() => {
            console.log(this.params); // works
        }, 500);
        console.log(this.params); // undefined
    }

    ngOnDestroy() {
        this.params$.unsubscribe();
    }
}

Затем вместо прямого присвоения выведите новое значение:

if (this._dialogConfig.contentParams) {
    this._dialogContentComponent.params$.next(this._dialogConfig.contentParams);
}

https://www.learnrxjs.io/subjects/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...