简体   繁体   English

在结构指令中访问 ViewChildren/ContentChildren

[英]Accessing ViewChildren/ContentChildren in a structural Directive

I would like to create a parent directive which shows or hides children based on the values of the children.我想创建一个父指令,它根据子项的值显示或隐藏子项。 To do this, i've taken the approach of a parent structural directive, and a child directive with values.为此,我采用了父结构指令和带有值的子指令的方法。 For simplicity without the values:为了简单起见,没有值:

<div *appParent>
  <div appChild>1</div>
  <div appChild>2</div>
  <div appChild>3</div>
  <div appChild>4</div>
</div>

To access the children, I use the following line in the parent directive:要访问子项,我在父指令中使用以下行:

 @ContentChildren(AppChildDirective, { read: AppChildDirective, descendents: true }) children: QueryList<AppChildDirective>;

This query list is always empty.此查询列表始终为空。 However, when I change it to a non-structural, it works fine.但是,当我将其更改为非结构性时,它工作正常。 Stackblitz demo here Stackblitz 演示在这里

I assume this is due to the fact the structural directive creates a parent ng-template , which @ContentChildren then looks inside to find the original component, meaning that the query actually goes nowhere.我认为这是由于结构指令创建了一个父ng-template@ContentChildren然后在里面查找原始组件,这意味着查询实际上无处可去。

What approach can I take to access the children of the original component and not the template?我可以采取什么方法来访问原始组件的子组件而不是模板? Or do I need to take another approach to handle my requirements?或者我是否需要采取其他方法来处理我的要求?

ContentChildren seem to not work on structural directives. ContentChildren 似乎不适用于结构指令。 However, this can be achived by injecting the parent directive in the child and then registering the child in the parent by calling a function.但是,这可以通过在子进程中注入 parent 指令,然后通过调用函数在父进程中注册子进程来实现。

@Directive({
  selector: '[appChild]'
})
export class ChildDirective {
  constructor(parent: ParentDirective) { 
    parent.registerChild(this);
  }
}

@Directive({
  selector: '[appParent]'
})
export class ParentDirective {
  registerChild(child: ChildDirective) { /*...*/ }
}

Side notes旁注

If you also want to be able to use the child directive without the parent directive, change the child's constructor like this to make the parent optional:如果您还希望能够在没有父指令的情况下使用子指令,请像这样更改子指令的构造函数以使父指令可选:

constructor(@Optional() parent: ParentDirective) { 
  parent?.registerChild(this);
}

You can also use this approach recursively by injecting a directive in its own constructor.您还可以通过在其自己的构造函数中注入指令来递归地使用这种方法。 If you do so, also add @SkipSelf() in the constructor to really get the parent:如果这样做,还要在构造函数中添加@SkipSelf()以真正获取父级:

@Directive({
  selector: '[appRecursive]'
})
export class RecursiveDirective {
  constructor(@Optional() @SkipSelf() parent: RecursiveDirective) { 
    parent?.registerChild(this);
  }

  registerChild(child: RecursiveDirective) { /*...*/ }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM