【问题标题】:Is there any way to do something, in order to ContentChildren could find components that are inside parent's <ng-content></ng-content>?有什么办法可以让 ContentChildren 找到父级 <ng-content></ng-content> 内的组件吗?
【发布时间】:2021-03-11 13:05:45
【问题描述】:

我有一些来自第三方库的组件,可以正常使用,下次使用时:

<lib>
  <lib-inner [text]="'111'"></lib-inner>
  <lib-inner [text]="'222'"></lib-inner>
</lib>

“lib”和“lib-inner”组件代码的简化模仿:

@Component({
  selector: "lib",
  template: `
    <ng-container *ngFor="let c of allInner;">
      <button>{{ c.text }}</button>
    </ng-container>
  `
})
export class LibComponent {
  @ContentChildren(LibInnerComponent) allInner: QueryList<LibInnerComponent>;
}
@Component({
  selector: "lib-inner",
  template: ``
})
export class LibInnerComponent {
  @Input() text: string;
}

我要创建包装组件:

<wrapper-for-lib>
  <lib-inner [text]="'aaa'"></lib-inner>
  <lib-inner [text]="'bbb'"></lib-inner>
</wrapper-for-lib>
@Component({
  selector: "wrapper-for-lib",
  template: `
    <lib>
      <ng-content></ng-content>
      <lib-inner [text]="'default'"></lib-inner>
    </lib>
  `
})
export class WrapperForLibComponent {}

当我们使用这个 'wrapper-for-lib' 组件时,我们只能看到 'default' 按钮,但看不到按钮 'aaa' 和 'bbb'。

'lib' 组件的 ContentChildren() 找不到 ng-content 中的 'lib-inner' 组件,

有没有办法解决这个问题?

注意,我无法更改“lib”和“lib-inner”的代码,因为它们模仿了真实第三方库组件的大小写,我无法更改。

workable example with above code

example for same case and real library component

【问题讨论】:

  • 尝试添加“descendants:true:@ContentChildren(LibInnerComponent,{descendants:true}),参见文档:angular.io/api/core/ContentChildren
  • 谢谢,我知道这个属性,但它不适用于这种情况,我也无法更改@ContentChildren,因为它是我使用的第三方库代码的模仿.

标签: angular ng-content


【解决方案1】:

我认为问题在于 lib-inner 呈现为空。尝试渲染一些内容,并将 ng-content 添加到 lib 组件中:

lib-inner.component.ts

import { Component, Input } from "@angular/core";

@Component({
  selector: "lib-inner",
  template: `<button>{{text }}</button>`
})
export class LibInnerComponent {
  @Input() text: string;
}

lib.component.ts

import { Component} from "@angular/core";

@Component({
  selector: "lib",
  template: `<ng-content></ng-content>`
})
export class LibComponent {

}

wrapper-for-lib.component.ts

import { Component } from "@angular/core";

@Component({
  selector: "wrapper-for-lib",
  template: `
    <lib>
      <ng-content></ng-content>
      <lib-inner [text]="'default'"></lib-inner>
    </lib>
  `
})
export class WrapperForLibComponent {}

编辑:见:https://stackblitz.com/edit/angular-kendo-toolbar-ng-conent-imitation-fazqq6?file=app%2Fwrapper-for-lib.component.ts

【讨论】:

  • 感谢您尝试回答,但首先我看不出与您的建议有什么不同 - 'lib' 组件中的 ContentChildren 仍然只能找到一个组件('default'),其次我无法更改'lib' 和 'lib-inner' 的代码,因为它们模仿真实第三方库的大小写。
  • 哦,对不起,代码没有保存。我更新了,见编辑。好的,我明白了,你不能改变 'lib' 或 'lib-inner',但是现在 lib-inner 什么都不渲染,我会尝试一些解决方法。
【解决方案2】:

您可以从包装器中选择所有 lib-inner 组件并将它们循环到模板中。

Component({
    selector: "wrapper-for-lib",
    template: `
    <lib>
        <ng-content></ng-content>
        <ng-container *ngFor="let inner of libInners">
            <lib-inner [text]="inner.text"></lib-inner>
        </ng-container>
    </lib>
`
})
export class WrapperForLibComponent {
    @ContentChildren(LibInnerComponent) libInners: QueryList<LibInnerComponent>;
  }

【讨论】:

  • 简单而好主意,它有效。而且我认为这是一个很好的解决方案。
猜你喜欢
  • 2017-09-21
  • 2020-11-03
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多