简体   繁体   English

角5:为所有ContentChildren(甚至子组件中的那些)获取一个QueryList

[英]Angular 5: Getting a QueryList for all ContentChildren (even the ones in sub components)

I have the following html structure where foo and bar are two directives and baz is a custom component. 我有以下html结构,其中foobar是两个指令,而baz是自定义组件。

<div foo>
  <div bar></div>
  <baz><baz>
  <baz><baz>
</div>

The html of the baz -component looks something like ... baz -component的html看起来像...

<div bar>Yada Yada Yada</div>

... and the foo -directive looks something like this: ...,而foo -directive看起来像这样:

// ...
@Directive({
  selector: '[foo]'
})
export class FooDirective implements AfterContentInit {

  @ContentChildren(BarDirective)
  m_bars: QueryList<BarDirective>;

  public ngAfterContentInit(): void {

    console.log('barCount:', this.m_bars.length);
  }
}

The problem I experience is that the length of m_bars inside the FooDirective is 1. It only contains the div that is a direct child of <div foo> . 我遇到的问题是,长度m_bars里面FooDirective是1只包含div是一个直接子<div foo> I however expected this number to be 3 (the one direct child of <div foo> and the other div 's inside the two baz -components). 但是,我希望这个数字为3( <div foo>的一个直接子级,两个baz -components内部的另一个div )。

Why is that so and how can this problem be solved - if it can be solved at all? 为什么会这样,如果完全可以解决,该如何解决呢?

Edit 1: Changing the ContentChildren decorator to 编辑1:将ContentChildren装饰器更改为

@ContentChildren(BarDirective, { descendants: true })
m_bars: QueryList<BarDirective>;

doesn't have any effect at all. 根本没有任何作用。

Check this StackBlitz out (watch for console output): https://stackblitz.com/edit/angular-h7ybb3 检查一下此StackBlitz(注意控制台输出): https ://stackblitz.com/edit/angular-h7ybb3

You would have to chain that through outputs. 您将必须通过输出将其链接起来。 QueryList has an Observable for changes, you could try using it as the output. QueryList具有可观察到的更改,您可以尝试将其用作输出。 Something along those lines: 遵循这些原则:

@ContentChildren() something: QueryList<Type>;

@Output() queryListChange = new EventEmitter();

ngOnInit() {
    this.something.changes.subscribe(v => {
        this.queryListChange.emit(v);
    }
}

And in the upper component you would need to subscribe to this output: 在上部组件中,您需要订阅以下输出:

(queryListChange)="onQueryListChange($event)"

And in onQueryListChange you would need to merge those items you received with component's own ViewChildren. 在onQueryListChange中,您需要将收到的那些项目与组件自己的ViewChildren合并。

And pass it along the same way if more levels of nesting is required. 如果需要更多级别的嵌套,则以相同的方式传递它。

I don't know a way to merge QueryLists so I just got original array from them and merged those in my stackblitz. 我不知道一种合并QueryList的方法,所以我只是从它们中获取原始数组,然后将它们合并到我的stackblitz中。

It's just not possible, which sucks. 只是不可能,这很糟糕。 See https://github.com/angular/angular/issues/20810#issuecomment-401341413 for further information. 有关更多信息,请参见https://github.com/angular/angular/issues/20810#issuecomment-401341413 I'll quote the tl;dr version for reference: 我将引用tl; dr版本以供参考:

In short: we only query component's own content, not content coming from other templates. 简而言之:我们仅查询组件自己的内容,而不查询其他模板的内容。 This makes sense since a template forms a namespace #foo in one template might mean one thing and completely different thing in another template. 这是有道理的,因为模板在一个模板中形成命名空间#foo可能意味着一件事,而在另一个模板中则意味着完全不同的事情。 Names might be the same but meaning quite different. 名称可能相同,但含义完全不同。

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

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