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--;
}
}
@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();
}
}