web-dev-qa-db-de.com

Angular Router: Wie werden Daten an das Lazy Loading-Modul übergeben?

Ich habe die folgenden Routing-Pfade für ein Modul meiner 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 {
}

Wie Sie sehen können, benutze ich die Eigenschaft data, um Daten an jeden Pfad in "Dokumenten" zu übergeben, damit ich sie von einer der in den Routing-Pfaden deklarierten Komponenten erhalten kann:

Zum Beispiel ist hier, wie ich Daten in DocumentDetailsComponent erhalte:

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

Jetzt habe ich die Routing-Struktur der gesamten App geändert und das obige Modul aus anderen Modulen mit dem loadChildren -Attribut beim verzögerten Laden aufgerufen. Und ich übergebe Daten auf die gleiche Weise:

@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 {
}

Und ich habe dasselbe für alle anderen Module getan, die DocumentsManagementRoutingModule aufrufen, und die Eigenschaft myObject entsprechend meinen Anforderungen in MyConstants.OPTION_TWO, MyConstants.OPTION_THREE Usw. geändert.

Wie erhalte ich dann die Eigenschaft data vom Aufrufermodul, da ich das Modul und den zugehörigen Pfad, der mein Lazy Loading-Modul aufruft, nicht kenne?

17
smartmouse

Sie können die übergeordneten Routen mithilfe von activateRoute.pathFromRoot durchlaufen und die Daten von dem nächstgelegenen Vorfahren abrufen, bei dem sie verfügbar sind. So etwas scheint zu funktionieren:

  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

6
rusmus

Ich glaube, ich kann verstehen, worum es bei der Frage geht.


Problem

Hier ist das Routing-Diagramm des Plunkers @smartmouse angegeben.

- home
  - shop
  - contact
    - map
  - about

In der Routenkonfiguration von data ist ein home Objekt konfiguriert. Die direkten untergeordneten Routen können auf dieses Datenobjekt zugreifen. Das Problem ist, dass das nicht direkte untergeordnete Objekt map auf das Objekt data zugreifen möchte, dies jedoch anscheinend nicht kann.

Und wir können wissen, dass @smartmouse Push möchte, dass verschachtelte nicht direkte untergeordnete Routen noch weiter auf Daten von Vorfahren zugreifen können .

Warum kann es nicht?

Schau dir den Plunker an, den ich modifiziert habe. https://plnkr.co/edit/FA7mGmspUXHhU8YvgDpT

Sie können sehen, dass ich eine zusätzliche untergeordnete Komponente DefaultComponent für contact definiere. Es zeigt, dass es sich um das direkte und standardmäßige untergeordnete Element von route contact handelt, was so interpretiert werden kann, dass es sich auch um das direkte untergeordnete Element von superior route home handelt. Es kann also auf das Objekt data zugreifen.

Lösung

Schauen Sie sich noch einmal den von mir gelieferten Plunker an.

HINWEIS: Die von mir verwendeten Angular - Pakete sind v4.3.0

Ansatz 1 - Abfrageparameter

Ich definiere einige Abfrageparameter in home.component.ts für contact route. Sie können sehen, wie man es benutzt.

Vorteile :

  • sie können über alle Routenebenen auf Abfrageparameter zugreifen.
  • funktioniert gut mit Lazyload-Modulen

Nachteile :

  • in route config können keine Abfrageparameter definiert werden.

    Sie können jedoch einige Routen-Lifecycle-Hooks verwenden, um sie für die Routen der Zielvorfahren zu definieren

Ansatz 2 - Service

Definieren Sie einen Datenfreigabedienst auf oberster Ebene der Anwendung, die als Singleton-Muster abgespielt wird. Verwenden Sie auch ein wenig util, um zu verhindern, dass es zweimal gestartet wird. Dann können Sie einige Daten darin ablegen und überall abrufen.

Vorteile :

  • global sichtbar über DI;
  • funktioniert gut mit Lazyload-Modulen

Nachteile :

  • sie können keine Daten in der Routenkonfiguration aktualisieren.
  • sie müssen Daten woanders definieren. Wenn Sie die Quelle nicht steuern können, liegt möglicherweise ein Problem vor.

Ansatz 3 - Routenauflösung

Jemand könnte herausfinden, dass ich im Plunker auch resolve Beispielcode definiert habe. Es soll zeigen, dass es dasselbe Verhalten hat wie data in der Routenkonfiguration, außer dass es sich tatsächlich um das dynamische Abrufen von Daten handelt.

https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab#54
Die Dateneigenschaft wird zum Übergeben eines festen Objekts an eine aktivierte Route verwendet. Sie ändert sich während der gesamten Lebensdauer der Anwendung nicht. Die Eigenschaft resolve wird für dynamische Daten verwendet.

Nehmen Sie das Beispiel von @ smartmouse.

Wir haben data in der 'home'-Routenkonfiguration definiert. Wir können einen Daten-Resolver in ContactModule für die Standardroute des Kontakts definieren und die von der übergeordneten Route übergebenen Daten als Proxy verwenden. Dann können alle ihre direkten untergeordneten Routen auf das Datenobjekt resolved zugreifen.

Vorteile :

  • funktioniert gut mit jeder Ebene von verschachtelten Routen
  • funktioniert gut mit Lazyload-Modulen

Nachteile :

  • Möglicherweise müssen Sie diese Auflösungseigenschaft in jeder übergeordneten Route deklarieren, deren untergeordnete Routen auf diese Daten zugreifen möchten. Es ist eine schmutzige Arbeit.

Derzeit gibt es keine perfekte und universelle Lösung mit der üblichen Verwendung von Angular. Jemand sollte die Vor- und Nachteile abwägen und das richtige auswählen.

10
e-cloud

Warum nutzen Sie den Service nicht, um die Daten zwischen den Modulen oder Komponenten auszutauschen? Sie können diesen Dienst beim Hauptmodulanbieter importieren lassen und können ihn daher in allen anderen Modulen (Lazy Loading Module) verwenden und die Daten gemeinsam nutzen.

Der Dienst kann Funktionen zum Festlegen und Abrufen von Werten enthalten. Daher können Sie diese Funktionen in Diensten verwenden, um die erforderlichen Daten abzurufen

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