0

I want to fetch data before an route/component is instantiated. Therefore I want to use the "Resolver"-Interface from the Angular2-Routing-Module.

Take a look at my code. Its working with a string as the provider name, but throwing errors if I use an OpaqueToken for the provider.

Watch out for the "NOT WORKING"-Comment.

1 My (Child-)Routes (excerpt).

export const routes: Routes = [{
path: 'myPath',
component: MyComponent,
children: [
    {
        path: ':id',
        component: MyComponent,
        resolve: {
            itemData: 'MyResolver' // WORKING --- wanted to replace with itemData: MyToken
        }
    }
]
}];

2 Code of my module (excerpt):

export let MyToken: OpaqueToken = new OpaqueToken('my.resolver');    

@NgModule({
        imports: [
            CommonModule,
            ...
        ],
        declarations: [
            MyComponent,
        ],
        providers: [
            {
                provide: 'MyResolver', // WORKING -- wanted to replace with provide: MyToken
                useFactory: (DataService: any) => {
                    return new MyResolverService(DataService);
                },
                deps: [MyInstanceOfDataService]
            }
        ]
    })
    export class MyModule {
    }

3 My custom Resolver-Class (excerpt):

@Injectable()
export class MyResolverService implements Resolve<any> {

    constructor(protected DataService: any) {
    }

    resolve(ActivatedRoute: ActivatedRouteSnapshot): Promise<any> {
        return this.DataService.getItem(id).toPromise()
                .then((response: any}) => {
                    return response;
                });
    }
}

Its not possible to replace the string ("myResolver") with the created OpaqueToken ("MyToken" - without quotes of course). Don´t know why. I use multiple OpaqueToken for several Providers, but the Resolver is not able to use it.

The Error message in the console looks like this without further information.

Error: Token must be defined!

Anyone any idea?

juli
  • 109
  • 1
  • 9
  • Why do you use `myToken` `myToken` with lowercase `m` in `resolve: { itemData: 'myResolver' // WORKING itemData: myToken // NOT WORKING` instead of `MyToken` and `MyResolver`? – Günter Zöchbauer Feb 25 '17 at 14:08
  • Just a typo - it´s correct now. – juli Feb 25 '17 at 14:11
  • 1
    Why do you use a token in the first place? Why not use the type of the service directly? It looks like you overcomplicate things, while still using `any` everywhere. – JB Nizet Feb 25 '17 at 14:12
  • Well, I want to use "MyResolverService" globally. Think about 2 modules, different Routes, and per module I have separate instances of my DataService (via FactoryProvider). When I call "MyResolverService" in above example I want to inject my DataService instance (see deps[MyInstanceOfDataService]) to reach the right API endpoint to fetch the data which needs to be resolved before opening the components view. Because of the global ResolverService I want to use the OpaqueToken for easier handling when the resolver is triggered by the routing-definition. – juli Feb 25 '17 at 14:16
  • (arg, cannot edit) ... and for easier handling I want to define in every module an OpaqueToken with same name to use it in every routing-definition, no matter which module is currently loaded. – juli Feb 25 '17 at 14:23

1 Answers1

0
// import MyResolver and MyToken here

export const routes: Routes = [{
path: 'myPath',
component: MyComponent,
children: [
    {
        path: ':id',
        component: MyComponent,
        resolve: {
            itemData: MyResolver
            itemData: MyToken
        }
    }
]
}];
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567