Async load routes data and build route instruction

2019-01-17 13:12发布

问题:

I try to build dynamically routes from angular2 (fetch route config from server), after that I parse it and generate instruction for component route (I have parent routes config and child into different components, because I don`t know how define route for child component into one main.app.ts file).

The problem is when app started and try to create routes config and routeGenerator is not build routes yet (async delay) cant parse routes data (because async delay, so routesData undefined now) and app is crashig. I dont know what to do with this. Looking for lifecycle hood (some like - @Angular2BeforeAppStarted ) but found nothing.

    import {Component, Input, OnChanges} from 'angular2/core';
import {RouteConfig, RouterOutlet, ROUTER_DIRECTIVES, Router} from 'angular2/router';
/* ------- !Angular 2 native components  ---------*/
import {routeGenInstance} from '../../config/routes/patient_routes';


protected const BUILT_MODULE_PATH: string = '/built/modules/patients/';

@Component({
  template: `
    <router-outlet ></router-outlet>
  `,
  directives: [RouterOutlet, ROUTER_DIRECTIVES]
})
@RouteConfig(routeGenInstance.getRouteDefinitions())

export class PatientsComponent {
  @Input();

  constructor() {}

}

Also i try to update routes in the same way (but app is crashed immediately because my Navigation link in navigation component is not have some correct link way)

import {RouteConfig, RouterOutlet, ROUTER_DIRECTIVES, Router} from 'angular2/router';

     constructor(
        private router: Router
         ) {
        router.config([
             routeGenInstance.getRoutesDefinition()
        ])
      }

my route definitions use Async loader so they are correct and work whithout async delay. I don`t know how to make angular wait for my routes definitions and thet start to run the app.

Please, help me. Thanks.

UPD:

@Thierry many thanks for your help again. You are awesome my friend and mentor. One last question (last). Can you tell me how I can define routeConfig into one app file with child subrouting definition? Its mean. I have main level routes into app files

{
  path: '/',
  name: 'Dashboard',
  component: DashboardComponent,
  useAsDefault: true
},
{
  path: '/patients/...',
  name: 'Patients',
  component: PatientsComponent
},

and patient sub routes into patientsComponent (@RouteConfig)

{
  path: '/',      // root is appRoot/patients/...
  name: 'PatientsList', component...},
  {
  "name": "Chart",
  "path": "/chart/:id", component...
},

How to define this route config only into one app.file ? (How to configure route with sub routing in one file)?

回答1:

An option could be to get your configuration before bootstrapping your application.

var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
var http = injector.get(Http);

http.get('routes.json').map(res => res.json())
  .subscribe(data => {
    bootstrap(AppComponent, [
      HTTP_PROVIDERS
      provide('routesConfig', { useValue: data })
    ]);
  });

Then you can have access the routes configuration by dependency injection and in a synchronous way:

@Component({
  (...)
})
export class AppComponent {
  constructor(@Inject('routesConfig') private routesConfig, private router:Router) {
    // Configure here your routes
  }
}

These two questions could help you:

  • How to bootstrap an Angular 2 application asynchronously
  • angular2 bootstrap with data from ajax call(s)

Edit

You can leverage the Observable.forkJoin method to load your route configuration from different requests:

var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
var http = injector.get(Http);

Observable.forkJoin([
  http.get('mainRoutes.json'),
  http.get('childRoutes.json')
])
.map(responses => {
  return {
    main: res[0].json(),
    children: res[1].json()
   };
 })
  .subscribe(data => {
    bootstrap(AppComponent, [
      HTTP_PROVIDERS
      provide('routesConfig', { useValue: data })
    ]);
  });

Edit1

I think that you could try something like that:

[
  {
    path: '/patients/...',
    name: 'Patients',
    component: PatientsComponent,
    childRoutes: [
      {
        path: '/',      // root is appRoot/patients/...
        name: 'PatientsList', component...
      },
      (...)
    ]
  }
]

But you need to split the content to get different elements according to the hints you want to handle:

  • one for the root:

    [
      {
        path: '/patients/...',
        name: 'Patients',
        component: PatientsComponent
      }
    ]
    
  • several for children. For example for patients:

    [
      {
        path: '/',      // root is appRoot/patients/...
        name: 'PatientsList', component...
      },
      (...)
    ]
    


回答2:

In the new router (>= RC.3) https://angular.io/docs/js/latest/api/router/index/Router-class.html#!#resetConfig-anchor resetConfig can be used

router.resetConfig([
 { path: 'team/:id', component: TeamCmp, children: [
   { path: 'simple', component: SimpleCmp },
   { path: 'user/:name', component: UserCmp }
 ] }
]);

See also https://github.com/angular/angular/issues/9472#issuecomment-229230093

  • You can load components asynchronously by providing a SystemJsComponentResolver.
  • Right now, you can load routes asynchronously and imperatively update the configuration using resetConfig.
  • Once AppModules are in master, we will utilize those to implement async loading of subconfigs.

https://github.com/angular/angular/issues/11437#issuecomment-245995186 provides an RC.6 Plunker



回答3:

Check this: DynamicalAsyncRouter

https://github.com/Longfld/DynamicalAsyncRouter



回答4:

Using Observables/Promises to provide route translations is not a reliable solution, hence the Angular router expects Route[] or Routes, but an HTTP request can only return an Observable/Promise.

The Angular app gets initialized, but the retrieval process of route translations still goes on using Observables/Promises.

As Thierry Templier said, to get your configuration before bootstrapping your application would solve the problem.

Also, check the @ngx-i18n-router/core on github.