Получить значение, переданное дочернему компоненту через атрибут ввода - PullRequest
2 голосов
/ 24 октября 2019

У меня большой проект, в котором я делаю несколько HTTP-вызовов GET для API, чтобы получить разные данные. Я хотел бы объединить их в один вызов (я уже создал его и вложил json со всеми данными), проблема в том, что я не могу передавать данные между компонентами. Позвольте мне объяснить проблему. Это вызов:

get(entityType: string): Promise<any> {
    return this.http
        .get<any>(
            this.location.prepareExternalUrl("./assets/temp-data/LEV_page/organisation.json")
        )
        .take(1)
        .toPromise();
}

В моем основном компоненте я делаю это:

public entityType:string;
public dataSource;

constructor(private levsService: LinkedEntityVocabulariesService) {}

ngOnInit() {
    this.entityType = localStorage.getItem("currentEntityType");
    this.levsService.get(this.entityType).then(data => {
        this.dataSource = data;
    });
}

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

<app-properties [send]="dataSource"></app-properties>

И затем просто получить к нему доступ:

@Input("send") send;

constructor() {}

ngOnInit() {
    console.log("test", this.send);
}

Все, что я получаю, это test undefined, потому чтоон передает его до получения данных (хотя я думал, что использование Promise вместо Observable предотвратит это).

В любом случае, мой вопрос: могу ли я позвонить, чтобы получить данные, а затем передатьэто между компонентами вместо вызова API снова? Если да, как я могу сделать это с приведенным выше примером? Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 24 октября 2019

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

<app-properties [send]="dataSource" *ngIf="dataSource"></app-properties>

Или вы можете внутри компонента app-properties проверить, определен ли dataSource, прежде чем пытаться что-либо с ним сделать,правильное место для этого - метод жизненного цикла ngOnChanges.

ngOnChanges() {
    if (this.send) {
        console.log(this.send);
    }
}
1 голос
/ 24 октября 2019

Что делает ваш компонент не отображающим новые данные, это Angular обнаружение изменений.

Это не сработало, к счастью, у angular есть встроенный асинхронный канал, который делает это для вас. Также эта труба отписывается от события так, что angular охватил вас все время.

Используйте этот подход:

public entityType:string;
public dataSource$: Observable<yourInterface>;

constructor(private levsService: LinkedEntityVocabulariesService) {}

ngOnInit() {
  this.entityType = localStorage.getItem("currentEntityType");
  this.datasource$ = this.levsService.get(this.entityType);
}

Тогда в вашем html используйте этот подход:

<app-properties [send]="dataSource$ | async"></app-properties>

И ваши данные будут загружены асинхронно.

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

Если вы хотите узнать больше, посмотрите здесь

0 голосов
/ 24 октября 2019

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

В Angular мы можем уменьшить этот APIвызов путем создания разделяемого объекта в службе (общий сервис). Я думаю, что здесь вы можете реализовать тему поведения. Объект должен инициализироваться или объявляться при запуске внутри службы и должен вызывать этот общий объект во всем приложении, вызывая службу в компоненте. Для этого вам нужно импортировать библиотеки из 'rxjs'

  private profileDataSource = new BehaviorSubject('');
  profileData = this.profileDataSource.asObservable();

Выше объявленного "profileDataSource" как BehaviorSubject со значением "". Я назвал это в первом компоненте после входа в систему и инициализировал это с деталями профиля. В нашем случае мы также обновляем этот объект, если пользователь обновляет данные профиля, это обновление будет отражаться при обновлении объекта BehavourSubject. Вы можете вызывать этот объект в компонентах и ​​использовать общие данные.

углубленное изучение предметов здесь https://rxjs -dev.firebaseapp.com / guide / subject

...