typescript - Angular 9 - @ContentChildren 的使用
我有一个ButtonGroupComponent,我需要在其中渲染两种类型的子组件:ButtonActionComponent或ButtonNavigationComponent。
我需要通过 @ContentChildren 来投射这些子组件,但我该怎么办,因为不可能同时传递两个选择器?
@ContentChildren(??)
public children: QueryList<??>;
所以,我尝试了另一种解决方案:我创建了一个组件,GroupableButtonComponent,该组件被两个组件(ButtonActionComponent 和 ButtonNavigationComponent)扩展。
然后我直接将这个组件传递给 ContentChildren:
@ContentChildren(GroupableButtonComponent)
public children: QueryList<GroupableButtonComponent>;
但我发现孩子仍然是空的。
我尝试的另一种解决方案是利用依赖注入并创建一个 GroupableButton 类:
export class GroupableButton {
}
在 ButtonActionComponent:
@Component({
selector: "button-action",
template: `
...
`,
providers: [{ provide: GroupableButton, useClass: ButtonActionComponent }],
})
export class ButtonActionComponent {
...
}
以及 ButtonNavigationComponent:
@Component({
selector: "button-navigation",
template: `
...
`,
providers: [{ provide: GroupableButton, useClass: ButtonNavigationComponent }],
})
export class ButtonNavigationComponent {
...
}
我这样使用它:
@ContentChildren(GroupableButton)
public children: QueryList<GroupableButton>;
但是因为在我的 ButtonGroupComponent 里面我有:
...
this.children
.toArray()
.slice(0, visibleButtons)
.reverse()
.forEach((button) => {
const factory = this.factoryResolver.resolveComponentFactory(
GroupableButton
);
const component = this.visibleButtonsContainer.createComponent(
factory,
0,
null,
[[button.element.nativeElement]]
);
this.clonePropertiesFrom(button, component.instance);
this.buttons.push(component);
});
...
这次的问题是我无法将 GroupableButton 作为 entryComponents 放入我的模块中。
答案#1
首先,不要使用你现有的提供者,做这个:
providers: [{ provide: GroupableButton, useExisting: forwardRef(() => ButtonActionComponent) }],
这将确保你获得正确的组件,并且可以根据需要循环使用你的组件。
我不确定这是否解决了你的实例化问题,但与其手动实例化你的组件,你有没有考虑过在组件模板中使用老式的 ng-content 标签?
<!-- put this where ever you want to project your buttons.... -->
<ng-content></ng-content>
答案#2
你把解决方案想得太复杂了。
为什么不直接通过字符串选择器查询这两个组件:
@ContentChildren('templateRef1, templateRef2') allTypesOfButtons: QueryList<ButtonActionComponent | ButtonNavigationComponent>;
我花时间在 Stackblitz 上放了一个例子
