Modificare dinamicamente il modello per un Angolare di 4 componenti

Utilizzando Angolare 4.1, sto cercando di modificare dinamicamente un modulo del tipo di modello prima che il modulo di reso. È possibile questo?

Siamo avvio di un imprecisato numero di componenti della pagina (da una lista di tipi di componenti), e la pagina può contenere più componenti dello stesso tipo. Ho trovato un modo per dare a ciascuno di questi componenti diversi selettore di modo che possano essere resi separatamente (anche se sono dello stesso tipo), ma ho anche la necessità di dare ad ognuno un modello diverso. , Il modello dovrebbe essere il codice HTML interno dell’elemento selezionato.

Ecco il codice:

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

Come notato verso la fine di codice di cui sopra, (<any>factory).factory.template = node.innerHTML; non funziona. Ho anche provato a modificare i metadati per il tipo, ma che non funziona, sia.

È quello che sto cercando di raggiungere possibile da un altro mezzo? Se non è questo che vale la pena di presentare una richiesta di funzionalità?

(Nota: il codice di cui sopra è in parte basato sul codice di altri https://github.com/angular/angular/issues/7136.)

Aggiornamento:

Mi chiedo se in un futuro aggiornamento di Angolare sarò in grado di ottenere lo stesso risultato impostando il modello <ng-content></ng-content> per includere l’innerHTML dell’elemento selezionato. Questo non è possibile, ora, con bootstrap componenti, ma sulla base di questo problema su Git, sono fiducioso che a breve sarà.

  • Stai usando AOT? Più precisamente, hai intenzione di spedire @angular/compiler alla produzione?
  • Sto diventando un blocco di nuovo Angolare e non impostare AOT compilazione di sicurezza, ma penso che l’utilizzo di AOT sarebbe l’ideale alla fine. Questo non cambia nulla? Sarei in grado di tirare fuori questo, se ho bloccato con il JIT?
  • Non posso capire tutti i dettagli della tua domanda, ma penso che si possa realizzare ciò che si desidera con l’uso di *ngFor e *ngSwitch strutturali direttiva. con il ngFor, è un ciclo per il numero totale di componente di cui hai bisogno. con il ngSwitch, si può poi scegliere liberamente tra il noto insieme di componenti a seconda di alcune variabili.
InformationsquelleAutor Kirk Grover | 2017-05-30



One Reply
  1. 5

    Non è possibile impostare un modello per un componente di fabbrica dopo che è stato creato. Angolare compilatore analizza i modelli durante la generazione di una fabbrica e crea una classe di visualizzazione per ogni componente. Dopo che il componente di fabbrica e la sua vista di classe sono creati non è possibile modificarlo. Nel tuo esempio si utilizza ComponentFactoryResolver

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

    che restituisce già creato in fabbrica.

    L’unica opzione è cambiare il modello prima che il compilatore genera fabbriche. Ma io non credo che sia possibile. Probabilmente si dovrà dare un’occhiata alla generazione dinamica di componenti.

    Leggere Qui è che cosa dovete conoscere circa i componenti dinamici in Angolare per ulteriori informazioni.

    • Grazie per la spiegazione e utile articolo, @Maximus. Quello che stai dicendo ha un senso. Ho intenzione di appendere su di speranza per un po ‘ che c’è un altro modo per ottenere questo prima di segnare la tua soluzione e la risposta e chiudere la porta all’idea di bootstrap componenti con i modelli dinamici.
    • Certo, nessun problema. I modelli devono essere compilati dal compilatore. Se si dispone di un modello compilato, quindi si può utilizzare per scopi diversi. È possibile ottenere modelli compilati con il ng-template direttiva. Ma non sono sicuro che questa soluzione funziona nel tuo caso.
    • Proprio come un punto di chiarimento – diciamo che ho un component.ts file e si desidera avere più diversi modelli di visualizzazione per esso (cioè component.1.html e component.2.html) – quello che stai dicendo è che non è possibile a livello di programmazione di scegliere quale modello di visualizzazione da usare?
    • Sarà necessario creare dinamicamente la classe di un componente. Leggi l’articolo ho fatto riferimento

Lascia un commento