从 SafeValue 访问@ContentChildren
Accessing @ContentChildren from SafeValue
我有一个简单的组件:
@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>
在SelectorComponent
的ngAfterContentInit
钩子中只得到3个结果(B、C、D元素)。如果元素 A 是 SafeValue
,我该如何访问它?
有什么方法可以跳过要求 SafeValue must use [property]=binding
(XSS 保护)?有没有其他方法可以访问此组件(我对访问 DOM 元素不感兴趣,而是获取组件引用)。
Angular 不知道使用 [innerHTML]
或其他 HTML 在运行时动态添加的内容。
Angular 在构建应用程序时编译模板,然后再部署,并忽略在运行时添加的所有 HTML。
您可以命令式执行
constructor(private elRef:ElementRef) {}
ngAfterContentInit() {
this.elRef.nativeElement.querySelector(...)
}
或者像
中解释的那样加载动态平台来编译组件 atr untime
感谢@Günter Zöchbauer 和 he has posted in one of the comments and the answer 我找到了解决方案:
我决定使用 ngComponentOutlet 正如文档所说:
NgComponentOutlet provides a declarative approach for dynamic component creation
首先我做了一个动态组件:
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 编译后,当 运行:
时出现错误
ERROR Error: Runtime compiler is not loaded
在评论之一的原始问题下,@Günter Zöchbauer 发布了 link 到 feature request 可以解决该问题。现在,如果您想使用这种方法,请不要使用 AoT 编译。
我有一个简单的组件:
@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>
在SelectorComponent
的ngAfterContentInit
钩子中只得到3个结果(B、C、D元素)。如果元素 A 是 SafeValue
,我该如何访问它?
有什么方法可以跳过要求 SafeValue must use [property]=binding
(XSS 保护)?有没有其他方法可以访问此组件(我对访问 DOM 元素不感兴趣,而是获取组件引用)。
Angular 不知道使用 [innerHTML]
或其他 HTML 在运行时动态添加的内容。
Angular 在构建应用程序时编译模板,然后再部署,并忽略在运行时添加的所有 HTML。
您可以命令式执行
constructor(private elRef:ElementRef) {}
ngAfterContentInit() {
this.elRef.nativeElement.querySelector(...)
}
或者像
感谢@Günter Zöchbauer 和
我决定使用 ngComponentOutlet 正如文档所说:
NgComponentOutlet provides a declarative approach for dynamic component creation
首先我做了一个动态组件:
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 编译后,当 运行:
时出现错误ERROR Error: Runtime compiler is not loaded
在评论之一的原始问题下,@Günter Zöchbauer 发布了 link 到 feature request 可以解决该问题。现在,如果您想使用这种方法,请不要使用 AoT 编译。