Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Dependency Injection and Barreling

I've had a issue with Dependency Injection when importing a service from a barrel (https://angular.io/docs/ts/latest/glossary.html#!#barrel).

The issue I've faced is this:

Using the Angular guidelines, in the app there's a core barrel and then a barrel for every folder, these are achieved by having an index.ts in each folder. The core index.ts references everything from each folder and in turn each folder references the specific files.

core index.ts

...
export * from './test/index';

test index.ts

...
export * from './my-service.service';

Code

import { MyService } from '../../core';
...

@Injectable()
export class AuthGuard implements CanActivate {
    isValidSession: boolean = false;
    errorMessage: any;

    constructor(
        private myService: MyService
    ) { }

    canActivate(
        // Not using but worth knowing about
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
    ) {
        return this.myService.doSomething();
    }
}

The above code resulted in the following error:

Uncaught Cannot resolve all parameters for 'AuthGuard'(undefined). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthGuard' is decorated with Injectable.

Looking at the code I did not find any issue with missing @Injectable annotations. In fact the same service was being used in other components and was imported using the core index.ts.

An article I found suggested that @Inject in the constructor should be used because sometimes when TypeScript is converted to JavaScript the metadata is not created. This did not solve the issue in my case. After trying several things I simply tried changing the import to get the service like below, and the error was not thrown.

Successful importation:

import { MyService } from '../../core/test/my-service.service';

or

import { MyService } from '../../core/test';

I'm not sure if there's an issue in the index.ts files in my application or maybe the file structure itself is wrong, but from what I can see they're working fine. Would like to know why this particular import is making a difference.

like image 640
Daniel Grima Avatar asked Jun 30 '16 08:06

Daniel Grima


1 Answers

I've had the exact same problem and Günter is right: The order of exports in the barrel does seem to matter.

In my case I had in my barrel:

export * from 'my.component'
export * from 'my.service'

which resulted in the same error that you saw. Putting the service before the component that's using it solved the problem:

export * from 'my.service'
export * from 'my.component'

I didn't find any documentation about this but I find this behavior definitely less than ideal because

  • it's implicit
  • it's not documented
  • the error-message doesn't give you any hints on how to fix it
like image 178
Philip Paetz Avatar answered Sep 25 '22 12:09

Philip Paetz