J'ai les chemins de routage suivants pour un module de mon Angular app:
@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 {
}
Comme vous pouvez le voir, j'utilise la propriété data
pour transmettre des données à chaque chemin dans les "documents", donc je peux les obtenir à partir de n'importe quel composant déclaré dans les chemins de routage:
Par exemple, voici comment obtenir des données dans 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();
}
}
Maintenant, j'ai changé la structure de routage de l'application entière et j'appelle le module ci-dessus à partir d'autres modules, en chargement paresseux, en utilisant l'attribut loadChildren
. Et je passe des données de la même manière:
@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 {
}
Et j'ai fait la même chose pour tous les autres modules qui appellent DocumentsManagementRoutingModule
, en changeant la propriété myObject
en MyConstants.OPTION_TWO
, MyConstants.OPTION_THREE
et ainsi de suite, selon mes besoins.
Puis, comme je ne connais pas le module et son chemin d'accès associé qui appelle mon module de chargement différé, comment obtenir la propriété data
à partir du module appelant?
Vous pouvez parcourir les itinéraires parents à l'aide de enabledRoute.pathFromRoot et obtenir les données de l'ancêtre le plus proche qui les a disponibles. Quelque chose comme ça semble fonctionner:
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--;
}
}
Je pense que je peux comprendre sur quoi porte la question.
Voici le graphe de routage du plunker @smartmouse fourni.
- home
- shop
- contact
- map
- about
Un objet data
est configuré sur la configuration de la route home
. Les routes enfants directes peuvent accéder à cet objet de données. Le problème est que l'enfant non direct map
veut accéder à l'objet data
, mais apparemment, il ne le peut pas.
Et nous pouvons savoir que @smartmouse veut pousser encore plus loin - les routes enfants imbriquées non directes peuvent accéder aux données de l'ancêtre .
Voir le plongeur que j'ai modifié. https://plnkr.co/edit/FA7mGmspUXHhU8YvgDpT
Vous pouvez voir que je définis un composant enfant supplémentaire DefaultComponent
pour contact
. Il montre que c'est l'enfant direct et par défaut de la route contact
, ce qui peut être interprété car c'est aussi l'enfant direct de la route supérieure home
. Ainsi, il peut accéder à l'objet data
.
Regardez à nouveau le plongeur fourni par moi.
REMARQUE: les packages Angular que j'utilise sont v4.3.0
Je définis certains paramètres de requête dans home.component.ts
pour contact
route. Vous pouvez voir comment l'utiliser.
Avantages :
Inconvénients :
vous ne pouvez pas définir de paramètres de requête dans la configuration de route.
Mais vous pouvez utiliser des crochets de cycle de vie de route pour les définir pour les routes ancêtres cibles
Définissez un service de partage de données au niveau supérieur de l'application jouant en tant que motif singleton. En outre, utilisez un util pour l'empêcher d'être lancé deux fois. Ensuite, vous pouvez y mettre des données et les récupérer n'importe où.
Avantages :
Inconvénients :
Quelqu'un peut découvrir que j'ai également défini resolve
exemple de code dans le plunker. C'est pour montrer qu'il a le même comportement que data
dans la configuration de route, sauf qu'il s'agit en fait de la récupération dynamique de données.
https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab#54
La propriété data est utilisée pour passer un objet fixe à une route activée. Il ne change pas pendant la durée de vie de l'application. La propriété de résolution est utilisée pour les données dynamiques.
Prenons l'exemple du plunkr de @ smartmouse.
Nous avons data
défini dans la configuration de la route 'home'. Nous pouvons définir un résolveur de données dans ContactModule
pour l'itinéraire par défaut du contact, et proxy les données transmises à partir de l'itinéraire supérieur. Tous ses itinéraires enfants directs peuvent alors accéder à l'objet de données résolu.
Avantages :
Inconvénients :
Il n'y a pas de solution parfaite et universelle, pour l'instant, avec une utilisation courante d'Angular. Quelqu'un devrait peser le pour et le contre et choisir le bon.
Pourquoi n'utilisez-vous pas le service pour partager les données entre les modules ou les composants. Vous pouvez avoir ce service importé chez le fournisseur de module principal et donc être utilisé dans tous les autres modules (module de chargement différé) et partager les données.
Le service peut avoir des fonctions pour définir et obtenir des valeurs et vous pouvez donc utiliser ces fonctions dans les services pour obtenir vos données requises
@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();
}
}