8

I am playing with Angular 2.0's new router and I try to use something similar to Angular 1.X ui-router / ng-route resolve mechanism.

I was trying to achieve this using RouteData:

import {Component, ViewEncapsulation} from 'angular2/core';
import {
  RouteConfig,
  ROUTER_DIRECTIVES
} from 'angular2/router';
// import {HTTP_PROVIDERS} from 'angular2/http';

import {HomeCmp} from '../home/home';
import {AboutCmp} from '../about/about';
import {NameList} from '../../services/name_list';
import {PersonalizationList} from '../../services/personalization_list';

@Component({
  selector: 'app',
  viewProviders: [NameList, PersonalizationList],
  templateUrl: './components/app/app.html',
  styleUrls: ['./components/app/app.css'],
  encapsulation: ViewEncapsulation.None,
  directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
  { path: '/', component: HomeCmp, as: 'Home', data: this.history },
  { path: '/about', component: AboutCmp, as: 'About' }
])
export class AppCmp {
  history: string[] = [];
  constructor(public list: PersonalizationList) {
    list.get('histoy', (response) => {
      this.history = response;
    });
  }
}

The component using this (home):

import {Component} from 'angular2/core';
import {PersonalizationList} from '../../services/personalization_list';
import {Router, ROUTER_DIRECTIVES, routerBindings, RouteConfig, RouteData} from 'angular2/router';

@Component({
  selector: 'home',
  templateUrl: './components/home/home.html',
  styleUrls: ['./components/home/home.css'],
  directives: [ROUTER_DIRECTIVES]
})
export class HomeCmp {
  constructor(data: RouteData) {
    console.log(data);
  }
}

The data logged to console is not the data I initialised from the service. If I initialise it directly in @RouteConfig, it will work. For example:

@RouteConfig([
  { path: '/', component: HomeCmp, as: 'Home', data: [1,2,3,4] },
  { path: '/about', component: AboutCmp, as: 'About' }
])

So, I'm missing the part of passing data from controller / component to @RouteConfig.

Another question - in Angular 1.X it was good practice to pass data to route via router's resolve. Is this still good practice to pass data to component this way, using the new router / components router?

Edit The solution can be found here - using the @CanActivate event

Community
  • 1
  • 1
Yaniv Efraim
  • 6,633
  • 7
  • 53
  • 96
  • Possible duplicate of [Angular2 : get parent router data](http://stackoverflow.com/questions/35299238/angular2-get-parent-router-data) – Jp_ Mar 04 '16 at 12:03
  • How can it be a duplicate if I asked my question almost 3 months before the other question? (: – Yaniv Efraim Mar 04 '16 at 19:51
  • Sorry, I'm not sure if it's right. I just looked who had more upvotes. – Jp_ Mar 04 '16 at 19:59
  • Possible duplicate of: http://stackoverflow.com/questions/33462532/using-resolve-in-angular2-routes – Philip Jul 09 '16 at 09:13

2 Answers2

8

You have to move your @RouteConfig into the AppCmp constructor:

//@RouteConfig([
//  { path: '/', component: HomeCmp, as: 'Home', data: this.history },
//  { path: '/about', component: AboutCmp, as: 'About' }
//])
export class AppCmp {
  history: string[] = [];
  constructor(public list: PersonalizationList,
              private router_: Router) {
    list.get('histoy', (response) => {
      this.history = response;
    });
    router_.config([
      { path: '/', component: HomeCmp, as: 'Home', data: this.history },
      { path: '/about', component: AboutCmp, as: 'About' }
    ]);
  }
}

On the console output I could see:

RouteData {data: "test sample"}

Hope it helps!

user3636086
  • 803
  • 1
  • 7
  • 10
  • will you please tell me whats the benifit of data in the routeConfig ? – Pardeep Jain Dec 15 '15 at 19:23
  • 1
    This solution is not perfect. It will pass the data (what I asked for), but it will not wait for data to be resolved. The best solution for this problem can be found [here](http://stackoverflow.com/a/34159997/916450) – Yaniv Efraim Dec 16 '15 at 07:58
7

update

@Injectable()
export class CrisisDetailResolve implements Resolve<Crisis> {
  constructor(private cs: CrisisService, private router: Router) {}
  resolve(route: ActivatedRouteSnapshot): Promise<Crisis>|boolean {
    let id = route.params['id'];
    return this.cs.getCrisis(id).then(crisis => {
      if (crisis) {
        return crisis;
      } else { // id not found
        this.router.navigate(['/crisis-center']);
        return false;
      }
    });
  }
}
  children: [
  {
    path: ':id',
    component: CrisisDetailComponent,
    canDeactivate: [CanDeactivateGuard],
    resolve: {
      crisis: CrisisDetailResolve
    }
  },
ngOnInit() {
  this.route.data
    .subscribe((data: { crisis: Crisis }) => {
      this.editName = data.crisis.name;
      this.crisis = data.crisis;
    });
}

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

original

The new router in RC.4 got resolve added

resolve is a map of DI tokens used to look up data resolvers. See Resolve for more info.

class TeamResolver implements Resolve {
  constructor(private backend: Backend) {}
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<any> {
    return this.backend.fetchTeam(this.route.params.id);
  }
}

bootstrap(AppComponent, [
  TeamResolver,
  provideRouter([{
    path: 'team/:id',
    component: TeamCmp,
    resolve: {
      team: TeamResolver
    }
  }])
);

See also RouterConfig

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 2
    Does this `resolve` consumer convert the observable to a promise and wait for the sequence to complete? Also I'd personally probably not want to bulk up my root namespace or bootstrap with dozens of resolver classes, each with only one specialized resolve operation; do you know of any examples of "provide a function with the same signature instead of the class", mentioned in the reference guide you linked? – shannon Jul 06 '16 at 19:49
  • I am really curious, if there are any plans for promised base resolve interface? see question: http://stackoverflow.com/questions/38270607/does-the-angular2-router-resolve-method-also-work-with-promises-instead-of-obser – Philip Jul 09 '16 at 07:26
  • 1
    You mean "promise-based"?. I guess not. It is easier to convert an observable to a promise than the other way around, but it seems observables are so ubiquitous that they don't bother supporting promises directly anymore. – Günter Zöchbauer Jul 09 '16 at 08:03
  • Thanks for the response. I'm struggling injecting the resolved data into the component. the http request goes through, but what method parameter should my component constructor include? I found https://angular.io/docs/ts/latest/api/router/index/ResolveData-type-alias.html, but it doesn't seem to help Can you extend your example? – Philip Jul 09 '16 at 08:17
  • 2
    thanks to a comment on this question (http://stackoverflow.com/questions/33462532/using-resolve-in-angular2-routes) You can access the resolved data via injecting the ```ActivatedRoute``` and get the ```route.snapshot.data``` attribute. – Philip Jul 09 '16 at 09:12