ng-template 中的 Angular 6 嵌套 ViewChild 为空

Erw*_*wol 8 javascript viewchild ng-bootstrap angular

我们在我们的应用程序中使用了一个模态(ng-bootstrap 的一个)。该模式看起来像:

<ng-template #modal let-modal>
    <app-audio #audio></app-audio>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

这是逻辑:

@ViewChild('modal')
modal: ElementRef;

@ViewChild('audio')
audio: AudioComponent;
Run Code Online (Sandbox Code Playgroud)

模态打开:

this.modalService.open(this.modal, { size: 'lg' });

一切都很好,直到这里。模态打开并显示音频组件。但是现在,我们想要访问组件内部的逻辑,并且在执行以下操作时:

this.audio.somePublicComponentFunction()

碰巧 this.audio 为空。我已经尝试让孩子使用 angular 的变化检测器,但找不到将 this.audio 与实际组件正确链接的方法。有任何想法吗?非常感谢。

你可以在这里看到这个问题:stackblitz.com/edit/angular-ofmpju

Ami*_*ani 5

您可以audio.someFunction()从模板本身调用该方法。

<ng-template #modal let-modal>
  <div style="background-color: red;"> 
  <h1>Modal header</h1>
  <app-audio #audio></app-audio>
  <!-- on click, call audio comp method someFunction() using its reference --> 
  <button (click)="audio.someFunction()">Operate with audio from inside modal</button>
  </div>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

@ViewChild这里不需要财产。这应该对你有用。

分叉演示


San*_*ijk 5

对我来说,所有这些解决方案都不起作用,我仍然想在第三方 ng-template 中访问我自己的组件。这是我的“解决方案”。我认为这不是最佳实践,而是获得我想要的东西的绝望解决方案;-) 当然,它仅适用于您自己的组件。

// mycomponent.ts => component that needs to be accessed 
import { Component, Output, EventEmitter, AfterViewInit } from '@angular/core';

@Component({
    selector: 'my-component',
    templateUrl: './mycomponent.html'
})
export class MyComponent implements AfterViewInit {
   @Output() initialized: EventEmitter<MyComponent> = new EventEmitter<MyComponent>();

   ngAfterViewInit(): void {
        this.initialized.emit(this);
   }

   reload(): void {
        // Do something
   }
}


// somecomponent.html => component with <ng-template> holding MyComponent

<ng-template>
    <div class="btn-group ml-2">
      <my-component (initialized)="onMyComponentInitialized($event)"></my-component>
    </div>
</ng-template>


// somecomponent.ts => component with <ng-template> holding MyComponent
import { Component, OnDestroy } from '@angular/core';
import { MyComponent } from '../../my-component';

@Component({
    selector: 'some-component',
    templateUrl: './some-component.html'
})
export class SomeComponent implements OnDestroy {
    private _myComponent: MyComponent = null;

    onMyComponentInitialized(component: MyComponent) {
        this._myComponent = component;
    }

    someOtherMethod() {
        if (this._myComponent) {
            // Call some method on the component
            this._myComponent.reload();
        }
    }

    ngOnDestroy() {
        this._myComponent = null;
    }
}
Run Code Online (Sandbox Code Playgroud)


Rah*_*hul 4

您可以在没有引用变量的情况下读取子组件,如下所示

@ViewChild(AudioComponent)
audio: AudioComponent;
Run Code Online (Sandbox Code Playgroud)

这将为您提供子组件的实例 - 您可以在其中访问该方法

this.audio.someComponentFunction()

你的html

<ng-template #modal let-modal>
    <app-audio></app-audio>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

我认为这将解决你的问题 - 快乐编码

更新:

希望我找到了解决此问题的方法 - 如果您只想触发一个功能,您可以使用此方法

我刚刚添加了一个带有getterand的属性,并在我们输入值setter时触发了该函数set

@Input()
  get triggerFunction(): boolean {
    return this.runFuntion;
  }

  set triggerFunction(value: boolean) {
    this.runFuntion = value;
    this.someFunction();
  }  
Run Code Online (Sandbox Code Playgroud)

因此,这会导致每次模型显示时都会触发该函数 - 上面提到的属性属于嵌套在内部的子组件,<ng-template>因此最终模型模板将如下所示读取:

<ng-template #modal let-modal>
  <app-audio [triggerFunction]="true"></app-audio>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

希望这能暂时解决问题 - 谢谢