2016-10-07 34 views
1

我正在使用第三方库来创建tabset。这是我用来创建一个简单的标签集如何使用@ViewChildren获取对未知子元素的引用

<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 > *'),假设只有一个每个选项卡下的孩子。

回答

1

只有两种方式支持

  • 传送一个组件或指令类型
  • 传递变量

其它要求的模板你可以注入ElementRef和直接访问使用ElementRef.nativeElement.... DOM的名称,但这样一来,你只能得到该元素不是组件或指令。

+1

谢谢,我可能最终钻入DOM和发射DOM事件的角度成分的可以听 –

+0

听起来像一个计划:) –

+0

我很想听听你对我的解决方案的反馈 –

1

问题的真正答案是as mentioned by Günter,这是无法完成的。除非您提前知道类型,否则无法查询。

我做两件事情

  • 创建可添加到标签集指令,这将触发对DOM事件砍死一个解决这个特定的问题最小化的代码量增加为每个标签<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); 
    } 
} 
+0

看起来不错对我来说。 –

相关问题