Angular 4 - @ViewChild 组件未定义

Angular 4 - @ViewChild component is undefined

我有一个名为 ToastComponent 的 toast 通知组件,我想从任何其他组件调用它。我是这样实现的:

ToastComponent:

export class ToastComponent implements OnInit {

  constructor() {}

  showToast() {
    // some code
  }
}

app.component.html:

<llqa-main-container>
  <llqa-header></llqa-header>
  <div class="content-container">
    <main class="content-area">
      <llqa-toast></llqa-toast> <!-- ToastComponent which I want to call -->
      <router-outlet></router-outlet>
    </main>
  </div>
</llqa-main-container>

UserManagementComponent 里面是 <router-outlet>:

export class UserManagementComponent implements OnInit {

  @ViewChild(ToastComponent) toast: ToastComponent;

  constructor() {}

  someSaveMethod() {
    this.toast.showToast() // throws error below
  }
}

在调用 someSaveMethod() 方法时,我会收到 toast 未定义的错误。

如果我从 app.component.html 中取出 <llqa-toast></llqa-toast> 并将其放在 user-management.component.html 的顶部,它工作正常,但我必须将它放在每个组件中。我怎样才能让它工作?

由于在您的情况下,ToastComponent 用于大 parent (AppComponent),这就是您收到此错误的原因。避免此错误的一种方法是使用某些共享服务中定义的 Subject。我在我的项目中使用这种方法来显示 toast 通知。方法如下:


让你的 <llqa-toast></llqa-toast> 保持在 app.component.html

定义一个服务,基本上发出一个事件并在您的 ToastComponent 中订阅该事件。例如,

UtilityService:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class UtilityService {

    public OnShowToast = new Subject<boolean>();

    public showToast(): void {
        this.OnShowToast.next(true);
    }
}

您需要在您的 AppModule 提供商中注入此服务。现在 subscribe 参加 ToastComponent 中的 OnShowToast 活动。

ToastComponent:

import { UtilityService } from './path/to/the/utility.service';
export class ToastComponent implements OnInit {

  constructor(private readonly utilityService: UtilityService) { }

  ngOnInit() { 
     this.utilityService.OnShowToast.subscribe(value =>
        {
            this.showToast();
        });
  }

  private showToast() {
    // some code
  }
}

现在,您可以从您想要的任何组件调用 UtilityServiceshowToast() 方法。例如,

UserManagementComponent

export class UserManagementComponent implements OnInit {

  // You dont need this now
  // @ViewChild(ToastComponent) toast: ToastComponent;

  constructor(private readonly utilityService: UtilityService) {}

  someSaveMethod() {
    this.utilityService.showToast();
  }
}