从SafeValue访问@ContentChildren

问题描述 投票:2回答:2

我有一个简单的组件:

@Component({
  selector: '[group_id]'
})
export class ItemComponent {}

我还有一个组件,我试图让所有传递给这个组件的孩子ItemComponent作为内容。

@Component({
    selector    : 'selector',
    template    : '<ng-content></ng-content>',
})
export class SelectorComponent implements AfterContentInit {
    @ContentChildren(ItemComponent) items;

    ngAfterContentInit() {
        console.log (this.items);
    }
}

现在我在应用程序的某个地方使用我的SelectorComponent

<selector>
    <div [innerHTML]="'<p group_id>A</p>' | safeHtml"></div>

    <p group_id>B</p>
    <p group_id>C</p>
    <p group_id>D</p>
</selector>

ngAfterContentInitSelectorComponent得到只有3个结果(B,C,D元素)。如果它是SafeValue,我如何访问元素A?

有没有办法跳过要求SafeValue must use [property]=binding(XSS保护)?是否有其他方法来访问此组件(我不想访问DOM元素,但获取组件引用)。

angular angular5
2个回答
1
投票

Angular不知道使用[innerHTML]或在运行时动态添加的其他HTML添加的内容。在构建应用程序之前,Angular在构建应用程序之前编译模板,并忽略运行时添加的所有HTML。

你可以要么必须这样做

constructor(private elRef:ElementRef) {}

ngAfterContentInit() {
  this.elRef.nativeElement.querySelector(...)
}

或加载动态平台以编译组件atr untime,如How can I use/create dynamic template to compile dynamic Component with Angular 2.0?中所述


1
投票

感谢@GünterZöchbauer和link,他发表了一条评论和答案here我找到了一个解决方案:

我决定使用ngComponentOutlet作为文档说:

NgComponentOutlet为动态组件创建提供了一种声明方法

首先,我制作了一个动态组件:

import {Component, OnChanges, OnInit, Input, NgModule,NgModuleFactory,Compiler, SimpleChanges} from '@angular/core';
import { SharedModule } from './shared.module';

@Component({
    selector: 'dynamic',
    template: `<ng-container *ngComponentOutlet="dynamicComponent;ngModuleFactory: dynamicModule;"></ng-container>`
})
export class DynamicComponent {

    dynamicComponent: any;
    dynamicModule   : NgModuleFactory<any>;

    @Input('html') html: string;

    constructor(private compiler: Compiler) {}

    ngOnChanges(changes: SimpleChanges) {
        if (changes['html'] && !changes['html'].isFirstChange()) {
            this.dynamicComponent = this.createNewComponent(this.html);
            this.dynamicModule    = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
        }
    }

    ngOnInit() {
        this.dynamicComponent = this.createNewComponent(this.html);
        this.dynamicModule    = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
    }

    protected createComponentModule(componentType: any) {
        @NgModule({
            imports     : [SharedModule],
            declarations: [
                componentType
            ],
            entryComponents: [ componentType ]
        })
        class RuntimeComponentModule {
        }
        // a module for just this Type
        return RuntimeComponentModule;
    }

    protected createNewComponent(template: string) {

        @Component({
            selector: 'dynamic-component',
            template: template ? template: '<div></div>'
        })
        class MyDynamicComponent {}

        return MyDynamicComponent;
    }
}

然后我将动态组件导入到我的模块中:

import { DynamicComponent } from './dynamic-item/dynamic-item';

@NgModule({
    declarations: [
        ...
        DynamicComponent,
    ],
    exports: [
        ...
        DynamicComponent,
    ]
})
export class ComponentsModule { }

不,我可以将动态组件与任何动态加载的html模板一起使用:

<dynamic [html]="dynamicHtml"></dynamic>

其中dynamicHtml可以通过包含任何现有组件/指令/等的任何html:

dynamicHtml: string = "<p group_id>A</p>";

值得注意的是,这种方法需要JIT编译器,因此在开发一切时工作正常,但在使用AoT进行编译后,运行时出错:

错误错误:未加载运行时编译器

根据其中一条评论中的原始问题,@GünterZöchbauer发布了feature request的链接,可以解决这个问题。目前,如果要使用此方法,请不要使用AoT编译。

© www.soinside.com 2019 - 2024. All rights reserved.