8

First: Yes, I have Googled this beforehand, and the solution that came up isn't working for me.

The Context

I have an Angular 2 component that calls a service, and needs to perform some data manipulation once it receives the response:

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

In its template, that data is passed to a child component:

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

This is causing an error that the child is getting myData as undefined. The Google result posted above talks about using Resolver but that isn't working for me.

When I create a new 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);

I get an error that there is no provider for MyDataResolver. This is still the case when I add MyDataResolver to the providers property in app.component.ts:

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

Has the interface for using this changed?

Community
  • 1
  • 1
A. Duff
  • 4,097
  • 7
  • 38
  • 69

1 Answers1

5

The router supports a promise or an observable returned from resolve().
See also https://angular.io/api/router/Resolve

This should do what you want:

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

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

See also https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard

ncse
  • 3
  • 2
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Based on the second link, I've added `MyResolver` to `providers` in **app.module.ts**, but `child-component` is still erroring because it's getting the data as undefined. Seems like it's still being instantiated before parent component has the data. Could this be because the parent component is what's waiting for the resolver, not the child component? But the child component doesn't have a route associated with it, and the parent component is the one fetching the data, so I'm not sure how else to make it wait. – A. Duff Sep 07 '16 at 14:31
  • Hard to tell what exactly your code is doing from this description. The simplest way would be adding an `*ngIf` like `` – Günter Zöchbauer Sep 07 '16 at 14:34
  • 1
    My mistake. I was still trying to extract it via the REST call in the parent component's constructor, rather than extracting it from the route data. Boneheaded of me, sorry. – A. Duff Sep 07 '16 at 14:43