297 votes

Appel d'une méthode de composant enfant à partir de la classe parent - Angular

J'ai créé un composant enfant qui possède une méthode que je veux invoquer.

Lorsque j'invoque cette méthode, elle ne déclenche que la fonction console.log() il ne définira pas la ligne test propriété ?

Voici l'application Angular de démarrage rapide avec mes modifications.

Parent

import { Component } from '@angular/core';
import { NotifyComponent }  from './notify.component';

@Component({
    selector: 'my-app',
    template:
    `
    <button (click)="submit()">Call Child Component Method</button>
    `
})
export class AppComponent {
    private notify: NotifyComponent;

    constructor() { 
      this.notify = new NotifyComponent();
    }

    submit(): void {
        // execute child component method
        notify.callMethod();
    }
}

Enfant

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'notify',
    template: '<h3>Notify {{test}}</h3>'
})
export class NotifyComponent implements OnInit {
   test:string; 
   constructor() { }

    ngOnInit() { }

    callMethod(): void {
        console.log('successfully executed.');
        this.test = 'Me';
    }
}

Comment puis-je définir le test la propriété également ?

0 votes

0 votes

Vous pouvez vérifier cette réponse ici : stackoverflow.com/a/53057589/6663458

391voto

rashfmnb Points 3666

Vous pouvez le faire en utilisant @ViewChild Pour plus d'informations, consultez ce site lien

Avec sélecteur de type

composant enfant

@Component({
  selector: 'child-cmp',
  template: '<p>child</p>'
})
class ChildCmp {
  doSomething() {}
}

composant parent

@Component({
  selector: 'some-cmp',
  template: '<child-cmp></child-cmp>',
  directives: [ChildCmp]
})
class SomeCmp {

  @ViewChild(ChildCmp) child:ChildCmp;

  ngAfterViewInit() {
    // child is set
    this.child.doSomething();
  }
}

Avec un sélecteur de chaîne

composant enfant

@Component({
  selector: 'child-cmp',
  template: '<p>child</p>'
})
class ChildCmp {
  doSomething() {}
}

composant parent

@Component({
  selector: 'some-cmp',
  template: '<child-cmp #child></child-cmp>',
  directives: [ChildCmp]
})
class SomeCmp {

  @ViewChild('child') child:ChildCmp;

  ngAfterViewInit() {
    // child is set
    this.child.doSomething();
  }
}

13 votes

J'ai suivi votre approche, mais je reçois une erreur lors de l'utilisation de d

17 votes

Comment faire pour que cela fonctionne lorsqu'il y a plusieurs enfants de la même classe ?

0 votes

@rashfmnb "Déclaration attendue". Une erreur survient lorsque j'essaie d'écrire @ViewChild('child') child:ChildCmp;dans le composant. Aidez-moi, s'il vous plaît ! De plus, je ne peux pas importer la même chose dans la directive, cela me donne une erreur du type "directive : (typeof EmployeeProfileC...' n'est pas assignable à un paramètre de type 'Component'. Un objet littéral ne peut spécifier que des propriétés connues, et 'directive' n'existe pas dans le type 'Component'".

140voto

user6779899 Points 71

Je pense que le moyen le plus simple est d'utiliser le sujet. Dans l'exemple de code ci-dessous, l'enfant sera notifié chaque fois que 'tellChild' est appelé.

Parent.component.ts

import {Subject} from 'rxjs/Subject';
...
export class ParentComp {
    changingValue: Subject<boolean> = new Subject();
    tellChild(){
    this.changingValue.next(true);
  }
}

Composant.parent.html

<my-comp [changing]="changingValue"></my-comp>

Child.component.ts

...
export class ChildComp implements OnInit{
@Input() changing: Subject<boolean>;
ngOnInit(){
  this.changing.subscribe(v => { 
     console.log('value is changing', v);
  });
}

Echantillon de travail sur Stackblitz

9 votes

Il s'agit d'une solution élégante, mais elle ne fonctionne pas correctement dans tous les cas, probablement parce que la détection des changements par Angular ne fonctionne pas à partir de subscribe.

1 votes

J'ai trouvé que c'était la meilleure solution pour mon cas d'utilisation. Elle fonctionne comme un charme. Merci !

1 votes

Neat ! Pour des cas plus simples, vous pouvez éviter la surcharge de Subject/Subscribe en passant un objet qui a une méthode de rappel à l'enfant. Comme ci-dessus, l'enfant surcharge le callback pour recevoir des indications du parent.

86voto

Kaur A Points 159

Cela a marché pour moi ! Pour Angular 2, appelez la méthode du composant enfant dans le composant parent.

Parent.component.ts

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { ChildComponent } from '../child/child'; 
    @Component({ 
               selector: 'parent-app', 
               template: `<child-cmp></child-cmp>` 
              }) 
    export class parentComponent implements OnInit{ 
        @ViewChild(ChildComponent ) child: ChildComponent ; 

        ngOnInit() { 
           this.child.ChildTestCmp(); } 
}

Child.component.ts

import { Component } from '@angular/core';
@Component({ 
  selector: 'child-cmp', 
  template: `<h2> Show Child Component</h2><br/><p> {{test }}</p> ` 
})
export class ChildComponent {
  test: string;
  ChildTestCmp() 
  { 
    this.test = "I am child component!"; 
  }
 }

4 votes

Qu'est-ce que ChildVM dans cette ligne : @ViewChild(ChildComponent ) child : ChildVM ;

0 votes

@WaleedShahzaib Je pense que l'OP voulait dire ChildComponent par ChildVM

1 votes

Je pensais que cela créerait une instance séparée du composant mais en fait, cela appelle la fonction de votre instance avec ses variables dans l'état actuel de ce composant, bon sang ! cette méthode est bien meilleure que la première réponse !

20voto

Hemant Ramphul Points 375

Angular - Appel de la méthode du composant enfant dans le modèle du composant parent

Vous avez un ParentComponent et un ChildComponent qui ressemble à ceci.

parent.component.html

enter image description here

parent.component.ts

import {Component} from '@angular/core';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
  constructor() {
  }
}

composant.enfant.html

<p>
  This is child
</p>

composant.enfant.ts

import {Component} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  constructor() {
  }

  doSomething() {
    console.log('do something');
  }
}

Au moment de servir, ça ressemble à ça :

enter image description here

Lorsque l'utilisateur met l'accent sur l'élément d'entrée du composant parent, vous voulez appeler la méthode doSomething() du composant enfant.

Faites simplement ceci :

  1. Donnez au sélecteur app-child dans parent.component.html un nom de variable DOM (préfixe avec # - hashtag) dans ce cas, nous l'appelons appChild.
  2. Attribuez la valeur de l'expression (de la méthode que vous voulez appeler) à l'événement de focus de l'élément d'entrée.

enter image description here

Le résultat :

enter image description here

14voto

shr Points 534

La réponse de user6779899 est soignée et plus générique Cependant, sur la base de la demande d'Imad El Hitti, une solution légère est proposée ici. Elle peut être utilisée lorsqu'un composant enfant est étroitement lié à un seul parent.

Parent.component.ts

export class Notifier {
    valueChanged: (data: number) => void = (d: number) => { };
}

export class Parent {
    notifyObj = new Notifier();
    tellChild(newValue: number) {
        this.notifyObj.valueChanged(newValue); // inform child
    }
}

Composant.parent.html

<my-child-comp [notify]="notifyObj"></my-child-comp>

Child.component.ts

export class ChildComp implements OnInit{
    @Input() notify = new Notifier(); // create object to satisfy typescript
    ngOnInit(){
      this.notify.valueChanged = (d: number) => {
            console.log(`Parent has notified changes to ${d}`);
            // do something with the new value 
        };
    }
 }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X