web-dev-qa-db-fra.com

Modification dynamique du modèle pour un Angular 4 composants

En utilisant Angular 4.1, j'essaie de changer dynamiquement le modèle d'un type de module avant le rendu du module. Est-ce possible?

Nous démarrons un nombre inconnu de composants sur la page (à partir d'une liste connue de types de composants), et la page peut contenir plusieurs composants du même type. J'ai trouvé un moyen de donner à chacun de ces composants un sélecteur différent afin qu'ils puissent être rendus séparément (même s'ils sont du même type), mais j'ai également besoin de donner à chacun un modèle différent. Le modèle doit être le code HTML interne de l'élément sélectionné.

Voici le code:

import { Component, NgModule, Inject, ApplicationRef, ComponentFactoryResolver, OpaqueToken, Type } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyNavComponent } from './MyNav.component';
import { MyRotatorComponent } from './MyRotator.component';
import { MySignUpComponent } from './MySignUp.component';

export const BOOTSTRAP_COMPONENTS_TOKEN = new OpaqueToken('bootstrap_components');

@NgModule({
    imports: [BrowserModule],
    declarations: [
        MyNavComponent,
        MyRotatorComponent,
        MySignUpComponent
    ],
    entryComponents: [
        MyNavComponent,
        MyRotatorComponent,
        MySignUpComponent
    ],
    providers: [
        {
            provide: BOOTSTRAP_COMPONENTS_TOKEN,
            useValue: [
                { type: MyNavComponent },
                { type: MyRotatorComponent },
                { type: MySignUpComponent }
            ]
        },
    ]
})
export class AppModule {
    constructor(
        private resolver: ComponentFactoryResolver,
        @Inject(BOOTSTRAP_COMPONENTS_TOKEN) private components: [Component],
    ) { }
    ngDoBootstrap(appRef: ApplicationRef) {
        console.log(this.components);
        this.components.forEach((componentDef: { type: Type<any>, selector: string }) => {
            const factory = this.resolver.resolveComponentFactory(componentDef.type);
            let selector = factory.selector;
            let nodes = document.querySelectorAll(selector);
            for (let i = 0; i < nodes.length; i++) {
                let node = nodes[i];
                (<any>factory).factory.selector = node;

                //The next line doesn't work... how can I dynamically set the template?
                (<any>factory).factory.template = node.innerHTML;

                appRef.bootstrap(factory);
            }
        });
    }
}

Comme indiqué à la fin du code ci-dessus, (<any>factory).factory.template = node.innerHTML; ne fonctionne pas. J'ai également essayé de modifier les métadonnées pour le type, mais cela ne fonctionne pas non plus.

Ce que j'essaie de réaliser est-il possible par un autre moyen? Sinon, cela vaut-il la peine d'être soumis en tant que demande de fonctionnalité?

(Remarque: le code ci-dessus est basé en partie sur le code des autres sur https://github.com/angular/angular/issues/7136 .)

Mise à jour:

Je me demande si dans une future mise à jour de Angular je pourrai obtenir le même résultat en définissant le modèle sur <ng-content></ng-content> pour inclure le innerHTML de l'élément sélectionné. Ce n'est pas possible maintenant avec des composants amorcés, mais sur la base de cela problème sur Git , j'espère que ce sera bientôt.

8
Kirk Grover

Vous ne pouvez pas définir de modèle pour une fabrique de composants après sa création. Angular analyse les modèles lors de la génération d'une fabrique et crée une classe de vue pour chaque composant. Une fois la fabrique de composants et sa classe de vue créées, vous ne pouvez plus la modifier. Dans votre exemple, vous utilisez ComponentFactoryResolver

const factory = this.resolver.resolveComponentFactory(componentDef.type);

qui renvoie une usine déjà créée.

La seule option est de changer le modèle avant que le compilateur ne génère des usines. Mais je ne pense pas que ce soit possible. Vous devrez probablement vous pencher sur la génération dynamique de composants.

Lisez Voici ce que vous devez savoir sur les composants dynamiques dans Angular pour plus d'informations.

5
Maxim Koretskyi