简体   繁体   English

当指令在带有异步 pipe 的 ngIf 中时,如何获取指令的 ViewChildren

[英]How can I get ViewChildren of a Directive when it is inside an ngIf with async pipe

I have a component that renders its content based on an observable with async pipe.我有一个组件,它基于带有异步 pipe 的 observable 呈现其内容。

<div *ngIf="equipment$ | async as equipment">
  <button myDirective></button>
</div>

In the.ts file, I'm getting all of the MyDirective children.在 .ts 文件中,我得到了所有的 MyDirective 孩子。 There can be any number.可以有任何数字。

@ViewChildren(MyDirective) actions!: QueryList<MyDirective>;

And then I want to access it in the ngAfterViewInit.然后我想在 ngAfterViewInit 中访问它。

ngAfterViewInit(): void {
  console.log(this.actions)
}

this logs a QueryList with 0 items.这会记录一个包含 0 个项目的 QueryList。 If I put the directive outside of my async pipe it all works perfectly:如果我将指令放在我的 async pipe 之外,它一切正常:

<div *ngIf="equipment$ | async as equipment">
  // Some HTML here
</div>
<button myDirective></button>

Is there any way I can retrieve the directives nested under the async pipe?有什么方法可以检索嵌套在异步 pipe 下的指令? I need to keep the ngIf because I have inputs bound to the equipment variable (which contains properties).我需要保留 ngIf,因为我将输入绑定到设备变量(包含属性)。

EDIT:编辑:

So, after thinking and thinking, I realized that what I'm trying to do here is to re-create NgRx.所以,想来想去,我意识到我在这里要做的是重新创建 NgRx。 After all this time thinking it was too complicated, I now understand all the benefits it brings and the problems it solves.经过这么长时间认为它太复杂了,我现在明白了它带来的所有好处和它解决的问题。 I'm gonna go ahead and try implementing it!我要提前 go 并尝试实现它!

you need to add static: false since it's a dynamically rendered component:您需要添加static: false因为它是动态呈现的组件:

@ViewChildren(MyDirective, { static: false }) actions!: QueryList<MyDirective>;

but you won't be sure that the directive will be available in ngAfterView init.但是您不能确定该指令在 ngAfterView init 中是否可用。 because equipment$ can take some time...因为equipment$可能需要一些时间...

maybe you can add a tap() in the observable and do your console.log() there istead也许你可以在 observable 中添加一个tap()并在那里做你的console.log()

You can create a hide directive, let me expain it:您可以创建一个隐藏指令,让我解释一下:

    @Input() hide: boolean;

constructor(private renderer: Renderer2, private elRef: ElementRef) {
}

ngOnChanges() {
    if (this.hide) {
        this.renderer.setStyle(this.elRef.nativeElement, 'visibility', 'hidden');
    } else {
        this.renderer.setStyle(this.elRef.nativeElement, 'visibility', 'visible');
    }
}

since the hide directive will not display the element on the dom but it can still be accesible因为 hide 指令不会在 dom 上显示元素,但它仍然可以访问

Simon, You can not access to an element that it's not in the screen when you execute an instruction.西蒙,执行指令时,您无法访问不在屏幕中的元素。

Of course you can not access in afterViewInit because the condition is yet false.当然你不能在 afterViewInit 中访问,因为条件仍然是假的。 So, you has two aproach所以,你有两种方法

  1. Create an observable based in yours and use rxjs operator tap根据您的创建一个可观察的并使用 rxjs 操作员点击

    equipmentDone$=this.equipment$.pipe( tap((res:any)=>{..here you has yet your this.actions... //it's possible, I'm not pretty sure you need enclosed in a setTimeout setTimeout(()=>{..here sure, sure you has this.actions.. }) }) )

    And use并使用

    <div *ngIf="equipmentDone$ | async as equipment"> <button myDirective></button> </div>
  2. Subscribe to the observable changes of the QueryList订阅 QueryList 的可观察变化

    ngAfterViewInit(){ this.actions.changes.subscribe(res=>{..here you has your actions.. }) }

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

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