Accessing Child Component Classes

@ViewChild and @ViewChildren

The @ViewChild and @ViewChildren decorators provide access to the class of child component from the containing component.

The @ViewChild is a decorator function that takes the name of a component class as its input and finds its selector in the template of the containing component to bind to. @ViewChild can also be passed a template reference variable.

For example, we bind the class AlertComponent to its selector <app-alert> and assign it to the property alert. This allows us to gain access to class methods, like show().

  1. import { Component, ViewChild } from '@angular/core';
  2. import { AlertComponent } from './alert.component';
  3. @Component({
  4. selector: 'app-root',
  5. template: `
  6. <app-alert>My alert</app-alert>
  7. <button (click)="showAlert()">Show Alert</button>`
  8. })
  9. export class AppComponent {
  10. @ViewChild(AlertComponent) alert: AlertComponent;
  11. showAlert() {
  12. this.alert.show();
  13. }
  14. }

View Example

In the interest of separation of concerns, we'd normally want to have child elements take care of their own behaviors and pass in an @Input(). However, it might be a useful construct in keeping things generic.

When there are multiple embedded components in the template, we can also use @ViewChildren. It collects a list of instances of the Alert component, stored in a QueryList object that behaves similar to an array.

  1. import { Component, QueryList, ViewChildren } from '@angular/core';
  2. import { AlertComponent } from './alert.component';
  3. @Component({
  4. selector: 'app-root',
  5. template: `
  6. <app-alert ok="Next" (close)="showAlert(2)">
  7. Step 1: Learn angular
  8. </app-alert>
  9. <app-alert ok="Next" (close)="showAlert(3)">
  10. Step 2: Love angular
  11. </app-alert>
  12. <app-alert ok="Close">
  13. Step 3: Build app
  14. </app-alert>
  15. <button (click)="showAlert(1)">Show steps</button>`
  16. })
  17. export class AppComponent {
  18. @ViewChildren(AlertComponent) alerts: QueryList<AlertComponent>;
  19. alertsArr = [];
  20. ngAfterViewInit() {
  21. this.alertsArr = this.alerts.toArray();
  22. }
  23. showAlert(step) {
  24. this.alertsArr[step - 1].show(); // step 1 is alert index 0
  25. }
  26. }

View Example

As shown above, given a class type to @ViewChild and @ViewChildren a child component or a list of children component are selected respectively using their selector from the template. In addition both @ViewChild and @ViewChildren can be passed a selector string:

  1. @Component({
  2. selector: 'app-root',
  3. template: `
  4. <app-alert #first ok="Next" (close)="showAlert(2)">
  5. Step 1: Learn angular
  6. </app-alert>
  7. <app-alert ok="Next" (close)="showAlert(3)">
  8. Step 2: Love angular
  9. </app-alert>
  10. <app-alert ok="Close">
  11. Step 3: Build app
  12. </app-alert>
  13. <button (click)="showAlert(1)">Show steps</button>`
  14. })
  15. export class AppComponent {
  16. @ViewChild('first') alert: AlertComponent;
  17. @ViewChildren(AlertComponent) alerts: QueryList<AlertComponent>;
  18. // ...
  19. }

View Example

Note that view children will not be set until the ngAfterViewInit lifecycle hook is called.

@ContentChild and @ContentChildren

@ContentChild and @ContentChildren work the same way as the equivalent @ViewChild and @ViewChildren, however, the key difference is that @ContentChild and @ContentChildren select from the projected content within the component.

Again, note that content children will not be set until the ngAfterContentInit component lifecycle hook.

View Example

原文: https://angular-2-training-book.rangle.io/handout/advanced-components/access_child_components.html