Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 component communication with router-outlet

Either I'm not getting the pattern or my design is wrong.

Using angular2-beta0, typescript

Basically I have set up a very basic application with a root component a router that controls main views and then on some pages I have a sub router to control the subviews on that component.

What I seem to be struggling with is how to structure things with communication between components. With the application as it is at the moment it's arranged in a way that makes logical sense to me, the main route's views have nothing in common and in the sub route views they all share the same side navigation and headers. The problem I have seems to be communicating back to the parent view of a sub-view. It seems to be that is a child is in a router-outlet it can't get the dependency of the parent component. I have looked at custom events but these only seem to work if bound to a template. The only other option seems to be a service but that seems broken to me as Ideally I want the parent component to be in control of the state of the sub components.

Any how some example code...

@Component({
    selector: 'app'
})

@View({
    template: '<router-outlet></router-outlet>',
    directives: [ROUTER_DIRECTIVES]
})

@RouteConfig([
    { path: '/', as: 'Login', component: LoginForm },
    { path: '/main/...', as: 'Main', component: Main}
])

class App {

    constructor(private _router: Router) {
    }

}

bootstrap(App, [ROUTER_PROVIDERS, provide(APP_BASE_HREF, { useValue: '/' })]);


@Component({
    selector: 'main'
})

@View({
    templateUrl: '/client/main/main.html',
    directives: [ROUTER_DIRECTIVES, NgClass, Menu, Main]
})

@RouteConfig([
    { path: '/', as: 'Clear', component: StateClear },
    { path: '/offer', as: 'Offer', component: StateOffer }
])

export class Main {

    constructor(private _router: Router) {

    }

}

@Component({
    selector: 'state-clear'
})

@View({
    templateUrl: '/client/bookings/state-clear.html'
})

export class StateClear {

    constructor(main: Main) {

    }
}

The error I'm getting with DI is this...

EXCEPTION: Cannot resolve all parameters for StateClear(undefined). Make sure they all have valid type or annotations.

No error with the event as I don't see how to listen outside of the template.

like image 980
gringo2150 Avatar asked Oct 18 '22 17:10

gringo2150


1 Answers

So what you might want to do is instead of using DI with parent components.

Like you are doing here :

export class StateClear {

    constructor(main: Main) {

    }
}

You might just want to create a service that handles the data you want to share within your route/component levels.

@Injectable()
export class UserSettingsService {
  // Application wide settings/config should be instatiated here
  // with a call from OnInit we can set all of these values.
  constructor() { }

  public iId: number;
  public userName: string;
  public isLoggedIn: boolean;
  public firstName: string;
  public lastName: string;
  public permissions: string[];
  getUser(userName:string) {
    // with an AJAX request get user Auth.
    return Promise.resolve(api.getUserAuth(userName));
  }
}

This UserSettingsService can now be added to your bootstrap as an application level service and can then be passed into all the routes you will want to share it with. dependency-injection-in-angular-2

bootstrap(App, [ROUTER_PROVIDERS, UserSettingsService, provide(APP_BASE_HREF, { useValue: '/' })]);

Then you do the following to gain access to that data within your component.

@Component({
    selector: 'state-clear'
})

@View({
    templateUrl: '/client/bookings/state-clear.html'
})

export class StateClear {
    userName:string;
    userId:int;
    isLoggedIn:boolean;
    constructor(private _userSettings: UserSettingsService) {
         // Not that you would do this here again but just for an example that the data is retrievable here.
         this.userName = this._userSettings.userName;
         this.userId = this._userSettings.iId;
    }
}
like image 149
inoabrian Avatar answered Nov 15 '22 06:11

inoabrian