1

我正在使用第三方库,可以让我创建标签集。这是我用来创建简单标签集的代码

<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 > *'),假设每个标签下只有一个孩子。

4

2 回答 2

2

只支持两种方式

  • 传递组件或指令类型
  • 传递模板变量的名称

对于其他要求,您可以直接使用注入ElementRef和访问 DOM,ElementRef.nativeElement....但这样您只能获取元素而不是组件或指令。

于 2016-10-07T14:29:17.390 回答
1

正如 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);
  }
}
于 2016-10-07T21:30:49.453 回答