动态更改 Angular 4 组件的模板 [英] Dynamically changing the template for an Angular 4 components

查看:25
本文介绍了动态更改 Angular 4 组件的模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Angular 4.1,我尝试在模块呈现之前动态更改模块类型的模板.这可能吗?

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

我们正在页面上引导未知数量的组件(来自已知的组件类型列表),并且页面可能包含多个相同类型的组件.我找到了一种方法,可以为这些组件中的每一个提供不同的选择器,以便它们可以单独呈现(即使它们属于相同类型),但我还需要为每个组件提供不同的模板.模板应该是所选元素的内部 HTML.

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.

代码如下:

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

如上述代码末尾处所指出的,(factory).factory.template = node.innerHTML; 不起作用.我也试过修改类型的元数据,但这也不起作用.

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?

(注意:以上代码部分基于https://https://github.com/angular/angular/issues/7136github.com/angular/angular/issues/7136.)

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

我想知道在未来的 Angular 更新中,我是否能够通过将模板设置为 <ng-content></ng-content> 来实现相同的结果包括所选元素的innerHTML.这对于引导组件现在是不可能的,但基于这个 问题 on Git,我希望很快.

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.

推荐答案

组件工厂创建后,您无法为其设置模板.Angular 编译器在生成工厂时解析模板并为每个组件创建一个视图类.创建组件工厂及其视图类后,您将无法对其进行修改.在您的示例中,您使用的是 ComponentFactoryResolver

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.

阅读这里是您需要了解的有关 Angular 中的动态组件的内容以获取更多信息.

这篇关于动态更改 Angular 4 组件的模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆