tag tab change angular lazy-loading angular-routing angular-module angular-router

tab - Enrutador angular: ¿cómo pasar los datos al módulo de carga diferida?



title angular (4)

¿Por qué no usa el servicio para compartir los datos entre los módulos o cualquier componente? Puede tener este servicio importado en el proveedor del módulo principal y, por lo tanto, puede utilizarse en todos los demás módulos (módulo de carga diferida) y compartir los datos.

El servicio puede tener funciones para establecer y obtener valores y, por lo tanto, puede hacer uso de estas funciones en los servicios para obtener los datos requeridos.

Tengo las siguientes rutas de enrutamiento para un módulo de mi aplicación Angular:

@NgModule({ imports: [ RouterModule.forChild([ { path: ''documents'', data: { myObject: MyConstants.OPTION_ONE }, children: [ { path: '':ID_DOC'', children: [ { path: ''edit'', component: EditDocumentComponent }, { path: '''', component: DocumentDetailsComponent }, ] }, { path: ''add'', component: AddDocumentComponent }, { path: '''', component: DocumentsListComponent } ] } ]) ], exports: [ RouterModule ] }) export class DocumentsManagementRoutingModule { }

Como puede ver, uso data propiedad de data para pasar algunos datos a cada ruta en "documentos", así que puedo obtenerla de cualquiera de los Componentes declarados en las rutas de enrutamiento:

Por ejemplo, aquí es cómo obtengo datos en DocumentDetailsComponent :

export class DocumentDetailsComponent implements OnDestroy { private obsData: Subscription; private option: any; constructor(private route: ActivatedRoute) { this.obsData = this.route.data.subscribe(data => { this.option = data[''myObject'']; }); } ngOnDestroy(): void { this.obsData.unsubscribe(); } }

Ahora cambié la estructura de enrutamiento de toda la aplicación y llamé al módulo anterior desde otros módulos, en carga loadChildren , usando el atributo loadChildren . Y paso datos de la misma manera:

@NgModule({ imports: [ RouterModule.forChild([ { path: ''users'', loadChildren: ''app/documents/documents.module#DocumentsModule'', data: { myObject: MyConstants.OPTION_ONE }}, { path: '':ID_USER'', children: [ { path: ''edit'', component: EditUserComponent }, { path: '''', component: UserDetailsComponent }, ] }, { path: ''add'', component: AddUserComponent }, { path: '''', component: UserListComponent } ]) ], exports: [ RouterModule ] }) export class UsersManagementRoutingModule { }

E hice lo mismo para todos los demás módulos que llaman a DocumentsManagementRoutingModule , cambiando la propiedad MyConstants.OPTION_TWO a MyConstants.OPTION_TWO , MyConstants.OPTION_THREE y así sucesivamente, según mis necesidades.

Entonces, dado que no conozco el módulo y su ruta relacionada que llama a mi módulo de carga diferida, ¿cómo obtener data propiedades de los data del módulo que llama?


Creo que puedo entender de qué se trata la pregunta.

Problema

Aquí está el gráfico de enrutamiento del plunker @smartmouse proporcionado.

- home - shop - contact - map - about

Hay un objeto de data configurado en la configuración de la ruta de home . Las rutas secundarias directas pueden acceder a este objeto de datos. El problema es que el map secundario no directo quiere acceder al objeto de data , pero aparentemente no puede.

Y podemos saber que @smartmouse quiere impulsar que aún más: las rutas secundarias no directas anidadas pueden acceder a los datos de los ancestros .

¿Por qué no puede?

Ver el plunker que he modificado. https://plnkr.co/edit/FA7mGmspUXHhU8YvgDpT

Puede ver que defino un componente secundario adicional DefaultComponent para contact . Muestra que es el hijo directo y predeterminado del contact de ruta, lo que puede interpretarse como también es el hijo directo de la ruta superior a home . Por lo tanto, puede acceder al objeto de data .

Solución

Mira el plunker proporcionado por mí otra vez.

NOTA: los paquetes angulares que estoy usando son v4.3.0

Enfoque # 1 - params de consulta

home.component.ts algunos parámetros de consulta en home.component.ts para la ruta de contact . Puedes ver como usarlo.

Pros :

  • Puede acceder a los parámetros de consulta en cualquier nivel de rutas.
  • Funciona bien con módulos de carga lenta.

Contras :

  • no se pueden definir parámetros de consulta en la configuración de ruta.

    Pero puede usar algunos enganches del ciclo de vida de la ruta para definirlos para las rutas del antepasado objetivo.

Enfoque # 2 - servicio

Defina un servicio de intercambio de datos en el nivel superior de la aplicación que se ejecuta como Singleton Pattern. Además, use alguna utilidad para evitar que se inicie dos veces. Luego puedes poner algunos datos en él y recuperarlos en cualquier lugar.

Pros :

  • global visible a través de DI;
  • Funciona bien con módulos de carga lenta.

Contras :

  • No puede actualizar los datos en la configuración de ruta.
  • Tienes que definir los datos en otro lugar. Si no puede controlar su fuente, puede ser un problema.

Enfoque # 3 - resolución de ruta

Alguien puede descubrir que también he definido el código de ejemplo de resolve en el plunker. Es para mostrar que tiene el mismo comportamiento que los data en la configuración de ruta, excepto que en realidad es para la recuperación dinámica de datos.

https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab#5400
La propiedad de datos se utiliza para pasar un objeto fijo a una ruta activada. No cambia a lo largo de la vida útil de la aplicación. La propiedad de resolución se utiliza para datos dinámicos.

Tomemos el ejemplo de @ smartmouse''s plunkr.

Tenemos data definidos en la configuración de ruta ''home''. Podemos definir un ContactModule datos en ContactModule para la ruta predeterminada del contacto, y representar los datos pasados ​​de la ruta superior. Entonces todas sus rutas secundarias directas pueden acceder al objeto de datos resuelto .

Pros :

  • Funciona bien con cualquier nivel de rutas anidadas.
  • Funciona bien con módulos de carga lenta.

Contras :

  • Es posible que tenga que declarar que resolver la propiedad en cada ruta principal cuyas rutas secundarias desea acceder a esos datos. Es una especie de trabajo sucio.

No hay una solución perfecta y universal, por ahora, con el uso común de Angular. Alguien debería sopesar los pros y los contras y elegir el adecuado.


Puede atravesar las rutas principales mediante el uso de enabledRoute.pathFromRoot y obtener los datos del antepasado más cercano que lo tenga disponible. Algo como esto parece funcionar:

ngOnInit(): void { let idx = this.activatedRoute.pathFromRoot.length - 1; while(this.sharedData == null && idx > 0){ this.sub = this.activatedRoute.pathFromRoot[idx].data.subscribe(subData => { if(subData.id) this.sharedData = subData; console.log(''shared data'', this.sharedData); }); idx--; } }

https://plnkr.co/edit/K5Rb1ZvTvSQNM6tOLeFp


@NgModule({ imports: [ RouterModule.forChild([ { path: ''users'', loadChildren: ''app/documents/documents.module#DocumentsModule'', resolve : { data: DataResolver } { ]) ], exports: [ RouterModule ] }) export class UsersManagementRoutingModule { } @Injectable() export class DataResolverimplements Resolve<Data> { resolve() { return this.serice.getData(); } }