Rufen Sie eine Methode der untergeordneten Komponente auf

75

Ich habe eine verschachtelte untergeordnete Komponente wie folgt:

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

Meine appMainKomponente muss eine Methode für die untergeordnete Komponente aufrufen.

Wie rufe ich eine Methode für die untergeordnete Komponente auf?

Per Hornshøj-Schierbeck
quelle

Antworten:

92

Mit können Sie einen Verweis auf ein Element erhalten

@ViewChild('childComponent') child;

Wo childComponentist eine Vorlagenvariable <some-elem #childComponent> `oder

@ViewChild(ComponentType) child;

Wo ComponentTypeist der Typ einer Komponente oder Direktive und dann in ngAfterViewInitoder ein Event-Handler-Aufruf child.someFunc().

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

Siehe auch Abrufen eines Elements in der Vorlage

Günter Zöchbauer
quelle
1
Ich denke, die Syntax ist @ViewChild(ComponentName) child;und laut den Dokumenten ist sie erst nach dem ngAfterViewInit()Lifecycle-Hook verfügbar .
Mark Rajcok
Ich versuchte es. Wenn eine Zeichenfolge übergeben wird, werden Vorlagenvariablen mit diesem Namen gesucht, andernfalls eine Komponente oder Direktive des übergebenen Typs. "Selector" in den Dokumenten ist etwas irreführend.
Günter Zöchbauer
1
Danke für das Update. Ich habe mir den Quellcode für ViewChild angesehen und dort steht "Unterstützt die gleichen Abfrageparameter wie QueryMetadata, außer Nachkommen." Das QueryMetadata-API-Dokument erläutert alle verschiedenen Arten von "Selektoren", die unterstützt werden. (Dieses Zeug zu finden ist im Moment so ein Schmerz.)
Mark Rajcok
52

Eltern und Kind können über Datenbindung kommunizieren.

Beispiel:

@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);  

Demo

#fErstellt einen Verweis auf die untergeordnete Komponente und kann in einer Vorlage verwendet oder an die Funktion übergeben werden. Daten vom Elternteil können durch [ ]Bindung übergeben werden.

Alexander Ermolov
quelle
Ich mache etwas falsch. Wenn ich eine Variable wie #f deklariere - dass #f sich auf das dom-Element bezieht und wenn ich f.someMethodCall () mache, erhalte ich einen Fehler, weil diese Methode für dieses Element nicht definiert ist. Weißt du was los ist?
Per Hornshøj-Schierbeck
2
@ PerHornshøj-Schierbeck, wenn es keine Komponente / Direktive für das Element gibt, #fbezieht sich die lokale Vorlagenvariable (z. B. ) auf das Element selbst. Vielleicht ist das dein Problem.
Mark Rajcok
@ PerHornshøj-Schierbeck Die Variable muss deklariert werden, bevor sie verwendet wird (Sie können nicht child-componentaus dem Beispiel als letztes in der Vorlage setzen)
Jan Zahradník
22

Eine Sohnkomponente sein

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

  data: number = 3;

  constructor() { }

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

}

Eine Vaterkomponente haben

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

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

In der Vorlage des Vaters

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

Diese Lösung funktioniert nur für eine <son></son>Instanz in der übergeordneten Vorlage. Wenn Sie mehr als eine Instanz haben, funktioniert dies nur in der ersten der Vorlage.

Pere Seiten
quelle
4
Sie können nur verwenden @ViewChildren(), um alle von ihnen zu bekommen.
Günter Zöchbauer
Das hat mich reingelegt! Mein Intellisense würde die Methoden der untergeordneten Komponenten nicht aufgreifen, was mich glauben lässt, dass sie nicht sichtbar sind! +1
Benscabbia
1

Der beste Weg, um auf eine untergeordnete Komponente zuzugreifen, ist @ViewChild .

Angenommen, Sie haben AppMainComponent mit einer verschachtelten ChildComponent aus Ihrem Beispiel.

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

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

export class AppMainComponent {}

Sie möchten eine eindeutige Methode aus Ihrer ChildComponent aufrufen.

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

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

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

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

Sie können dies erreichen, indem Sie die ChildComponent-Klasse, den ViewChild-Dekorator und die darin enthaltene Komponentenklasse als Abfrage importieren. Auf diese Weise hätten Sie Zugriff auf die in der benutzerdefinierten Variablen gespeicherte Schnittstelle der ChildComponent. Hier ist ein Beispiel:

// 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();
    }
}

Beachten! Die untergeordnete Ansicht wird erst nach ngAfterViewInit verfügbar .

Antworten Sie, nachdem Angular die Ansichten und untergeordneten Ansichten der Komponente initialisiert hat. Wird einmal nach dem ersten ngAfterContentChecked () aufgerufen. Ein Haken nur für Komponenten.

Wenn Sie die Methode automatisch ausführen möchten, müssen Sie dies innerhalb dieses Lebenszyklus-Hooks tun.

Sie können auch eine QueryList mit untergeordneten Komponenten über ViewChildren Decorator abrufen .

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

...

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

QueryList kann sehr nützlich sein, z. B. können Sie untergeordnete Änderungen abonnieren.

Es ist auch möglich, Vorlagenreferenzvariablen zu erstellen und über den ViewChild-Dekorator darauf zuzugreifen.

Frelseren
quelle