Every time I generate something in my shared folder the index.ts file is rebuilt and exports are put in alphabetical order. This seems to break dependencies for me. Changing order manually so that dependencies is exported before classes with the dependencies makes it work again.
If we have app/shared/auth.guard.ts
:
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { AuthService, User } from './';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private accountService: AuthService, private router: Router) { }
canActivate(next: ActivatedRouteSnapshot): Observable<boolean> {
let result = this.accountService.currentUser.first().map(user => user != null);
let route: any[] = ['/login'];
if (next.url.length) {
route.push({ redirectUrl: next.url });
}
result.subscribe(isLoggedIn => {
if (!isLoggedIn) {
this.router.navigate(route);
}
});
return result;
}
}
and app/shared/account.service.ts
:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { User } from './';
const LOCAL_STORAGE_KEY = 'currentUser';
@Injectable()
export class AuthService {
private currentUserSubject: BehaviorSubject<User>;
constructor() {
this.currentUserSubject = new BehaviorSubject<User>(this.getUserFromLocalStorage())
this.currentUserSubject.subscribe(user => this.setUserToLocalStorage(user));
}
logIn(userName: string, password: string) : Observable<User> {
this.currentUserSubject.next({
id: userName,
userName: userName,
email: userName
});
return this.currentUser.first();
}
logOut() {
this.currentUserSubject.next(null);
}
get currentUser(): Observable<User> {
return this.currentUserSubject.asObservable();
}
private getUserFromLocalStorage(): User {
let userString = localStorage.getItem(LOCAL_STORAGE_KEY);
if (!userString) {
return null;
}
return JSON.parse(userString);
}
private setUserToLocalStorage(user: User) {
if (user) {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(user));
}
else {
localStorage.removeItem(LOCAL_STORAGE_KEY);
}
}
}
This doesn't work:
export * from './auth.guard';
export * from './auth.service';
Unhandled Promise rejection: Error: Cannot resolve all parameters for 'AuthGuard'(undefined, Router). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthGuard' is decorated with Injectable.
This works:
export * from './auth.service';
export * from './auth.guard';
From what I noticed this doesn't apply to all. For example can my user model be exported after auth service and it works fine.
I wish I didn't have to change this manually every time. Is there a workaround available? Could I structure the files in a different way?
Dependencies from package.json
:
"@angular/common": "^2.0.0-rc.2",
"@angular/compiler": "^2.0.0-rc.2",
"@angular/core": "^2.0.0-rc.2",
"@angular/forms": "^0.1.0",
"@angular/http": "^2.0.0-rc.2",
"@angular/platform-browser": "^2.0.0-rc.2",
"@angular/platform-browser-dynamic": "^2.0.0-rc.2",
"@angular/router": "^3.0.0-alpha.7",
"bootstrap": "^3.3.6",
"es6-shim": "0.35.1",
"moment": "^2.13.0",
"ng2-bootstrap": "^1.0.17",
"reflect-metadata": "0.1.3",
"rxjs": "5.0.0-beta.6",
"slideout": "^0.1.12",
"systemjs": "0.19.26",
"zone.js": "0.6.12"
devDependencies:
"angular-cli": "1.0.0-beta.6"
This is an issue with ordering of exports in barrels. It has been reported in the angular repo here: https://github.com/angular/angular/issues/9334
There are three workarounds:
Change the ordering so that module dependencies are listed before their dependants.
In this example, AuthGuard depends on AuthService. AuthService is a dependency of AuthGuard. Therefore, export AuthService before AuthGuard.
export * from './auth.service';
export * from './auth.guard';
This is not recommended since it means more imports are required.
In this example, you would import AuthService from its file rather than a barrel.
import { AuthService } from './auth.service';
import { User } from './';
Change the typescript compiler options to compile to the SystemJS format rather than commonJS. This is done by changing tsconfig.json's compilerOptions.module
from commonjs
to system
.
Note that when you change that configuration, you'll need to update the moduleId
properties of all your component decorators from module.id
to __moduleName
and declare it in typings.d.ts
as follows:
declare var __moduleName: string;
This module format is not the default in the Angular-CLI tool (official build tool created by the Angular team) and so may not be recommended or supported.
Note: I'm personally not satisfied with any of the workarounds.
I had this issue and this was caused by circular reference. Explanations : within the 'provider service class' I had a reference to a UI page that the constructor referenced this same service causing the circular reference...
import { MyUIPage } from "../pages/example/myuipage";
So what I had to do, is remove the reference from the service and built a function receiving a callback. No need to reference the UI page from the service and error goes away.
public setCallBackSpy(callback)
{
this.callBackSpy = callback;
}
In the app.component class constructor, the one referencing the service, I simply set the link to the callback function like below.
this.servicingClass.setCallBackSpy(this.myCallBackFunctionUsingUIPage);
Hope that helps, my first answer ever :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With