angular - Angular 9 - use of @ContentChildren
问题描述
I have a ButtonGroupComponent in which i need to render two types of children: ButtonActionComponent or ButtonNavigationComponent.
I need to project these children via @ContentChildren, but what can i do, since it is not possible to pass both selectors?
@ContentChildren(??)
public children: QueryList<??>;
So, I tried another solution: I created a component, GroupableButtonComponent, which is extended by the two (ButtonActionComponent and ButtonNavigationComponent).
And then I passed directly this component to ContentChildren:
@ContentChildren(GroupableButtonComponent)
public children: QueryList<GroupableButtonComponent>;
But I found that children remains empty.
Another solution I tried was to exploit dependency injection and create a GroupableButton class:
export class GroupableButton {
}
where ButtonActionComponent:
@Component({
selector: "button-action",
template: `
...
`,
providers: [{ provide: GroupableButton, useClass: ButtonActionComponent }],
})
export class ButtonActionComponent {
...
}
and ButtonNavigationComponent:
@Component({
selector: "button-navigation",
template: `
...
`,
providers: [{ provide: GroupableButton, useClass: ButtonNavigationComponent }],
})
export class ButtonNavigationComponent {
...
}
I used it this way:
@ContentChildren(GroupableButton)
public children: QueryList<GroupableButton>;
but since inside my ButtonGroupComponent I have:
...
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);
});
...
this time the problem is that I can't pass GroupableButton as entryComponents inside my module.
解决方案
first, instead of the providers you have, do this:
providers: [{ provide: GroupableButton, useExisting: forwardRef(() => ButtonActionComponent) }],
this will ensure you're getting the correct component and can loop your components as you see fit.
I'm not sure this solves your instantiation issue, but instead of manually instantiating your components, have you considered the good old ng-content
tag in your component template?
<!-- put this where ever you want to project your buttons.... -->
<ng-content></ng-content>
推荐阅读
- css - CSS 实用程序类应该有“!important”关键字吗?
- pipenv - Pipenv 锁定:命令“python setup.py egg_info”失败,错误代码为 1(Windows 10)
- reactjs - 反应钩子 useEffect 和 ref 对象中的奇怪行为
- database - 从 130 小时提高 PostgreSQL pg_restore 性能
- javascript - 为什么要在 monorepo 的根级 package.json 中声明包 - lerna
- python - 用 Turtle python 着色数字
- reactjs - 在 Jest 测试中未定义作为 prop 传递的 React 组件状态
- scala - 在 Spark 中过滤 RDD 后如何获取键的第一个值?
- c# - C# 属性命名
- javascript - 如何替换 QueryString 中 JSON 包装中与某个键匹配的值?