Как заставить Angular2 ждать обещания перед рендерингом компонента

Во-первых: да, я заранее погуглил это, и решение, которое мне пришло, не работает.

Контекст

У меня есть компонент Angular 2, который вызывает службу и должен выполнить некоторые манипуляции с данными после получения ответа:

ngOnInit () {
  myService.getData()
    .then((data) => {
      this.myData = /* manipulate data */ ;
    })
    .catch(console.error);
}

В его шаблоне эти данные передаются дочернему компоненту:

<child-component [myData]="myData"></child-component>

Это вызывает ошибку, что дочерний элемент получает myData как неопределенное. Результат Google, опубликованный выше, говорит об использовании Resolver, но это не работает для меня.

Когда я создаю новый преобразователь:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Rx';
import { MyService } from './my.service';

@Injectable()
export class MyResolver implements Resolve<any> {
    constructor(private myService: MyService) {}

    resolve (route: ActivatedRouteSnapshot): Observable<any> {
        return Observable.from(this.myService.getData());
    }
}

app.routing.ts

const appRoutes: Routes = [
  {
    path: 'my-component',
    component: MyComponent,
    resolve: {
        myData: MyDataResolver
    }
  }
];

export const routing = RouterModule.forRoot(appRoutes);

Я получаю сообщение об ошибке, что нет провайдера для MyDataResolver. Это все еще имеет место, когда я добавляю MyDataResolver к свойству providers в app.component.ts:

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.component.html',
  providers: [
        MyService,
        MyResolver
  ]
})

Изменился ли интерфейс для использования этого?


person A. Duff    schedule 06.09.2016    source источник
comment
Можете ли вы реализовать дочернее свойство myData в качестве установщика и проверить там наличие «неопределенного»?   -  person rook    schedule 07.09.2016
comment
Это MyResolver или MyDataResolver. Код в вашем вопросе кажется противоречивым.   -  person Günter Zöchbauer    schedule 07.09.2016


Ответы (1)


Маршрутизатор поддерживает обещание или наблюдаемое значение, возвращенное resolve().
См. также https://angular.io/api/router/Resolve

Это должно делать то, что вы хотите:

@Injectable()
export class MyResolver implements Resolve<any> {
    constructor(private myService: MyService) {}

    resolve (route: ActivatedRouteSnapshot): Promise<any> {
        return this.myService.getData();
    }
}

См. также https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard

person Günter Zöchbauer    schedule 07.09.2016
comment
Основываясь на второй ссылке, я добавил MyResolver к providers в app.module.ts, но child-component по-прежнему выдает ошибку, поскольку получает данные как неопределенные. Похоже, что он все еще создается до того, как родительский компонент получит данные. Может ли это быть связано с тем, что родительский компонент ожидает распознавателя, а не дочерний компонент? Но дочерний компонент не имеет связанного с ним маршрута, а родительский компонент извлекает данные, поэтому я не уверен, как еще заставить его ждать. - person A. Duff; 07.09.2016
comment
Из этого описания сложно сказать, что именно делает ваш код. Самый простой способ - добавить *ngIf как <child-component *ngIf="data" [myData]="myData"></child-component> - person Günter Zöchbauer; 07.09.2016
comment
Виноват. Я все еще пытался извлечь его с помощью вызова REST в конструкторе родительского компонента, а не извлекать его из данных маршрута. Тупой с моей стороны, извините. - person A. Duff; 07.09.2016