Викличте метод дочірнього компонента


77

У мене є такий вкладений дочірній компонент:

<app-main>
    <child-component />
</app-main>

Моєму appMainкомпоненту потрібно викликати метод дочірнього компонента.

Як викликати метод дочірнього компонента?

Відповіді:


96

Ви можете отримати посилання на елемент за допомогою

@ViewChild('childComponent') child;

де childComponent- змінна шаблону <some-elem #childComponent> `або

@ViewChild(ComponentType) child;

де ComponentType- тип компонента або директиви, а потім - ngAfterViewInitабо виклик обробників подій child.someFunc().

ngAfterViewInit() {
  console.log(this.child);
}

Див. Також отримання елемента в шаблоні


1
Я думаю, що синтаксис є, @ViewChild(ComponentName) child;і згідно з документами, він буде недоступний до ngAfterViewInit()підключення життєвого циклу.
Mark Rajcok

Я спробував. Коли передається рядок, він шукає шаблонні змінні з цим іменем, інакше компонент або директива переданого типу. "Селектор" у документах дещо вводить в оману.
Günter Zöchbauer

1
Дякуємо за оновлення. Я подивився вихідний код ViewChild , і там написано: "Підтримує ті самі параметри запиту, що і QueryMetadata, крім нащадків". API док QueryMetadata пояснює все різні типи «селектори», які підтримуються. (На даний момент це дуже боляче знайти.)
Марк Райчок

52

Батьки та дитина можуть спілкуватися через прив'язку даних.

Приклад:

@Component({
    selector: 'child-component',
    inputs: ['bar'],
    template: `"{{ bar }}" in child, counter  {{ n }}`
})
class ChildComponent{
    constructor () {
        this.n = 0;
    }
    inc () {
        this.n++;
    }
}

@Component({
    selector: 'my-app',
    template: `
        <child-component #f [bar]="bar"></child-component><br>
        <button (click)="f.inc()">call child func</button>
        <button (click)="bar = 'different'">change parent var</button>
    `,
    directives: [ChildComponent]
})
class AppComponent {
    constructor () {
        this.bar = 'parent var';
    }
}

bootstrap(AppComponent);  

Демо

#fстворює посилання на дочірній компонент і може використовуватися в шаблоні або передаватися функції. Дані від батьків можна передати шляхом [ ]прив'язки.


Я роблю щось не так. Коли я оголошую змінну, як #f - це #f посилається на елемент dom, а коли я роблю f.someMethodCall (), я отримую помилку, оскільки цей метод не визначений для цього елемента. Ви знаєте, що не так?
Per Hornshøj-Schierbeck

2
@ PerHornshøj-Schierbeck, якщо в елементі відсутній компонент / директива, локальна змінна шаблону (наприклад, #f) посилається на сам елемент. Можливо, це ваша проблема.
Mark Rajcok

@ PerHornshøj-Schierbeck змінна повинна бути оголошена перед її використанням (ви не можете вказати child-componentприклад, як останній у шаблоні)
Ян Захраднік,

22

Будучи синовим компонентом

@Component({
    // configuration
    template: `{{data}}`,
    // more configuration
})
export class Son {

  data: number = 3;

  constructor() { }

  updateData(data:number) {
    this.data = data;
  }

}

Наявність батьківського компонента

@Component({
    // configuration
})
export class Parent {
  @ViewChild(Son) mySon: Son;

  incrementSonBy5() {
    this.mySon.updateData(this.mySon.data + 5);
  }
}

У шаблоні батька

<son></son>
<button (click)="incrementSonBy5()">Increment son by 5</button>

Це рішення працює лише для одного <son></son>екземпляра в батьківському шаблоні. Якщо у вас більше одного екземпляра, це буде працювати лише в першому шаблоні.


4
Ви можете просто скористатися @ViewChildren()ними.
Günter Zöchbauer

Це мене обдурило! Мій intellisense не збирав методи дочірніх компонентів, що змушує мене думати, що це не було видно! +1
benscabbia

1

Найкращий спосіб отримати доступ до дочірнього компонента - @ViewChild .

Скажімо, у вас є AppMainComponent із вкладеним ChildComponent із вашого прикладу.

// app-main.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'app-main',
    template: `
        <child-component />
    `
})

export class AppMainComponent {}

Ви хочете викликати чіткий метод з вашого ChildComponent.

// child.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'child-component',
    template: '{{ greeting }}'
})

class ChildComponent {
    greeting: String = 'Hello World!';

    clear() {
        this.greeting = null;
    }
}

Ви можете досягти цього, імпортуючи клас ChildComponent, декоратор ViewChild і передавши в нього клас компонента як запит. Таким чином, ви отримаєте доступ до інтерфейсу ChildComponent, що зберігається у користувацькій змінній. Ось приклад:

// app-main.component.ts
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './components/child/child.component';

@Component({
    selector: 'app-main',
    template: `
        <child-component />
    `
})

class ChildComponent {
    @ViewChild(ChildComponent)
    child: ChildComponent;

    clearChild() {
        this.child.clear();
    }
}

Зверніть увагу! Дочірній вигляд стає доступним лише після ngAfterViewInit .

Відповідь після того, як Angular ініціалізує подання компонента та дочірні подання. Викликається один раз після першого ngAfterContentChecked (). Гачок лише для компонентів.

Якщо ви хочете виконати метод автоматично, вам потрібно зробити це всередині цього гачка життєвого циклу.

Ви також можете отримати QueryList дочірніх компонентів через декоратор ViewChildren .

import { Component, ViewChildren, QueryList } from '@angular/core';
import { ChildComponent } from './components/child/child.component';

...

@ViewChildren(ChildComponent)
children: QueryList<ChildComponent>;

QueryList може бути дуже корисним, наприклад, ви можете підписатися на дитячі зміни.

Також можна створити посилальні змінні шаблону та отримати доступ до них через декоратор ViewChild.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.