Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何使用@ViewChildren获取对未知子元素的引用_Angular_Viewchild - Fatal编程技术网

Angular 如何使用@ViewChildren获取对未知子元素的引用

Angular 如何使用@ViewChildren获取对未知子元素的引用,angular,viewchild,Angular,Viewchild,我正在使用第三方库来创建选项卡集。这是我用来创建一个简单选项卡集的代码 <clr-tabs (clrTabsCurrentTabContentChanged)="onTabContentActivated($event)" > <clr-tab-link>Firewall</clr-tab-link> <clr-tab-link>DHCP</clr-tab-link> <clr-tab-

我正在使用第三方库来创建选项卡集。这是我用来创建一个简单选项卡集的代码

<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>

我愿意接受任何建议,我想也许我可以将选项卡的索引与类似
@QueryChildren('clr-tab-content>*')
的内容相匹配,假设每个选项卡下只有一个子项。

支持两种方式

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

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

问题的真正答案是无法完成。除非提前知道类型,否则无法查询

我通过做两件事,找到了一个解决这个问题的方法,最大限度地减少了为每个选项卡添加的代码量

  • 创建可添加到选项卡集的指令,该指令将在
    的子元素上触发DOM事件
  • 创建一个函数,用于连接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);
  }
}

防火墙
DHCP
//lazy-tab-loader.directive.ts
@指示({
选择器:“[vcd惰性选项卡加载程序]”
})
导出类VcdLazyTabLoader{
构造函数(@Inject(forwardRef(()=>Tabs))私有选项卡集:选项卡,
私人el:ElementRef){
tabSet.currentTabIndexChanged.subscribe((tabIndex)=>{
//不是很漂亮,我们以后会找到更好的方法
//它依赖于clr选项卡内容的内部HTML结构
const element=this.el.nativeElement.querySelectorAll(`clr tab content`)[tabIndex]
.firstElementChild.firstElementChild;
元素。dispatchEvent(新的CustomEvent(“vcd已激活”),{});
});
}
}
导出接口CanLoadData{
loadData():void;
}
导出函数setupLazyLoader(el:HtmleElement,dataLoader:CanLoadData){
el.addEventListener('vcd-激活',()=>{
loadData();
});
}
//firewall-tab.component.ts(和dhcp tab.components.ts)
@组件(…)
//标签的第一块胶水(实现CanLoadData)
类FirewallTab实现CanLoadData{
构造函数(私有防火墙服务:防火墙服务,
私人el:ElementRef){
//第二块胶水,每个标签
//构造函数不是最好的地方,它在这里只是为了避免额外的代码
setupLazyLoader(el.nativeElement,本);
}
加载数据(){
this.service.getRules().subscribe((数据)=>this.rules=rules);
}
}

谢谢,我可能会钻入DOM并触发一个DOM事件,角度组件可以像计划一样聆听声音:)我很想听听您对我的解决方案的反馈。我觉得很好。
<!-- 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);
  }
}