Dynamically changing the template for an Angular 4 components

和自甴很熟 提交于 2019-12-10 02:58:48

问题


Using Angular 4.1, I'm trying to dynamically change a module type's template before the module rendered. Is this possible?

We are bootstrapping an unknown number of components on the page (from a known list of component types), and the page may contain multiple components of the same type. I've found out a way to give each of these components a different selector so they can be rendered separately (even if they're of the same type), but I also need to give each one a different template. The template should be the inner HTML of the selected element.

Here's the 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);
            }
        });
    }
}

As noted near the end of the above code, (<any>factory).factory.template = node.innerHTML; doesn't work. I've also tried modifying the metadata for the type, but that doesn't work, either.

Is what I'm trying to achieve possible by another means? If not, is this worth submitting as a feature request?

(Note: the above code is based in part on the code of others at https://github.com/angular/angular/issues/7136.)

Update:

I'm wondering if in a future update of Angular I'll be able to achieve the same result by setting the template to <ng-content></ng-content> to include the innerHTML of the selected element. This isn't possible now with bootstrapped components, but based on this issue on Git, I'm hopeful it will be soon.


回答1:


You cannot set a template for a component factory after it was created. Angular compiler parses templates when generating a factory and creates a view class for each component. After the component factory and its view class are created you cannot modify it. In your example you're using ComponentFactoryResolver

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

which returns already created factory.

The only option is to change the template before the compiler generates factories. But I don't think it's possible. You will probably have to take a look at the dynamic generation of components.

Read Here is what you need to know about dynamic components in Angular for more information.



来源:https://stackoverflow.com/questions/44272519/dynamically-changing-the-template-for-an-angular-4-components

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!