我正在使用第三方库,可以让我创建标签集。这是我用来创建一个简单的tabset的代码
<clr-tabs
(clrTabsCurrentTabContentChanged)="onTabContentActivated($event)" >
<clr-tab-link>Firewall</clr-tab-link>
<clr-tab-link>DHCP</clr-tab-link>
<clr-tab-content>
<vcd-firewall-tab></vcd-firewall-tab>
</clr-tab-content>
<clr-tab-content>
<vcd-dhcp-tab></vcd-dhcp-tab>
</clr-tab-content>
</clr-tabs>
我已经联系了一个事件,告诉我何时选择了标签,并且我想在loadData()
和<vcd-firewall-tab>
上调用<vcd-dhcp-tab>
方法。
clrTabsCurrentTabContentChanged
会给我一个对所选clr-tab-content
的引用,但我想访问它的第一个孩子,并调用loadData()
来实现延迟加载。
我想我可以使用@QueryChildren
注释,除了我必须指定要查询的元素类型。问题是,在这种情况下,我不知道类型,它可能是<vcd-firewall-tab>
,<vcd-dhcp-tab>
或我们拥有的许多其他标签,我不想每次都添加自定义代码我添加了一个新标签。
我希望能够从我的事件处理程序中执行类似的操作(但这不存在)
onTabContentActivated(tabContent: TabContent){
(tabContent.query(':first-child') as CanLoadData).loadData();
}
我愿意接受任何建议,我想也许我可以将标签的索引与@QueryChildren('clr-tab-content > *')
匹配,假设每个标签下只有一个孩子。
答案 0 :(得分:1)
支持的方式只有两种
对于其他要求,您可以注入ElementRef
并使用ElementRef.nativeElement....
直接访问DOM,但这样您只能获得元素而不是组件或指令。
答案 1 :(得分:1)
问题as mentioned by Günter的真正答案是无法完成。除非您提前知道类型,否则无法查询。
我通过做两件事来破解这个特定问题的解决方案,最大限度地减少了为每个标签添加的代码量
<clr-tab-contents>
的子元素上触发DOM事件。loadData()
这是一个实现它的最小例子。它非常粗糙,我的真实代码处理其他极端情况,但我不想在解决方案中添加噪声。
<!-- One piece of glue per tabset -->
<clr-tabs vcd-lazy-tab-loader>
<clr-tab-link>Firewall</clr-tab-link>
<clr-tab-link>DHCP</clr-tab-link>
<clr-tab-content>
<vcd-firewall-tab></vcd-firewall-tab>
</clr-tab-content>
<clr-tab-content>
<vcd-dhcp-tab></vcd-dhcp-tab>
</clr-tab-content>
</clr-tabs>
// lazy-tab-loader.directive.ts
@Directive({
selector: '[vcd-lazy-tab-loader]'
})
export class VcdLazyTabLoader {
constructor(@Inject(forwardRef(() => Tabs)) private tabSet: Tabs,
private el: ElementRef) {
tabSet.currentTabIndexChanged.subscribe((tabIndex) => {
// Not very pretty, we'll find a nicer way later
// It relies on the internal HTML structure of clr-tab-content
const element = this.el.nativeElement.querySelectorAll(`clr-tab-content`)[tabIndex]
.firstElementChild.firstElementChild;
element.dispatchEvent(new CustomEvent("vcd-activated", {}));
});
}
}
export interface CanLoadData {
loadData(): void;
}
export function setupLazyLoader(el: HTMLElement, dataLoader: CanLoadData) {
el.addEventListener('vcd-activated', () => {
dataLoader.loadData();
});
}
// firewall-tab.component.ts (AND dhcp-tab.components.ts)
@Component(...)
// First piece of glue (implement CanLoadData) for a tab
class FirewallTab implements CanLoadData {
constructor(private firewallService: FirewallService,
private el: ElementRef) {
// Second piece of glue, per tab
// Constructor is not the best place, it's here just to avoid extra code
setupLazyLoader(el.nativeElement, this);
}
loadData () {
this.service.getRules().subscribe((data)=> this.rules = rules);
}
}