208 votes

Comment émettre un événement de parent à enfant ?

J'utilise actuellement Angular 2. Habituellement, nous utilisons @Output() addTab = new EventEmitter<any>(); et ensuite addTab.emit() pour émettre un événement vers le composant parent.

Y a-t-il un moyen de le faire vice cersa, de parent à enfant ?

4 votes

Il suffit de modifier la valeur d'une expression transmise en tant que Input au composant enfant, et ce dernier la recevra (et sera informé par ngOnChanges). Vous pouvez également émettre un événement en utilisant un service partagé qui possède un Observable.

416voto

Blue Points 760

Utilisation de RxJs vous pouvez déclarer un Subject dans votre composant parent et le passer comme Observable au composant enfant, ce dernier n'a qu'à s'abonner à ce code. Observable .

Parent-Composant

eventsSubject: Subject<void> = new Subject<void>();

emitEventToChild() {
  this.eventsSubject.next();
}

Parent-HTML

<child [events]="eventsSubject.asObservable()"> </child>    

Composante enfant

private eventsSubscription: Subscription;

@Input() events: Observable<void>;

ngOnInit(){
  this.eventsSubscription = this.events.subscribe(() => doSomething());
}

ngOnDestroy() {
  this.eventsSubscription.unsubscribe();
}

37 votes

Cette approche permet également de transmettre des données avec l'événement. Comme, this.eventsSubject.next({data}); dans le parent, alors this.events.subscribe(({data}) => doSomething(data)); dans l'enfant.

8 votes

J'ai modifié cette excellente réponse pour ajouter la désinscription. +1

3 votes

Il s'agit probablement d'une question de débutant : Pourquoi convertir eventsSubject à un Observable au lieu de simplement s'y abonner en tant que sujet ?

133voto

prajwal gonsalves Points 422

Pour autant que je sache, il y a deux façons standard de le faire.

1. @Input

Chaque fois que les données du parent sont modifiées, l'enfant en est informé par le biais de la méthode ngOnChanges. L'enfant peut agir en conséquence. Il s'agit de la manière standard d'interagir avec un enfant.

Parent-Component
public inputToChild: Object;

Parent-HTML
<child [data]="inputToChild"> </child>       

Child-Component: @Input() data;

ngOnChanges(changes: { [property: string]: SimpleChange }){
   // Extract changes to the input property by its name
   let change: SimpleChange = changes['data']; 
// Whenever the data in the parent changes, this method gets triggered. You 
// can act on the changes here. You will have both the previous value and the 
// current value here.
}
  1. Concept de service partagé

Créer un service et utiliser un observable dans le service partagé. L'enfant s'y abonne et chaque fois qu'il y a un changement, l'enfant sera notifié. C'est également une méthode populaire. Lorsque vous voulez envoyer quelque chose d'autre que les données que vous passez en entrée, vous pouvez l'utiliser.

SharedService
subject: Subject<Object>;

Parent-Component
constructor(sharedService: SharedService)
this.sharedService.subject.next(data);

Child-Component
constructor(sharedService: SharedService)
this.sharedService.subject.subscribe((data)=>{

// Whenever the parent emits using the next method, you can receive the data 
in here and act on it.})

0 votes

J'ai essayé la première méthode et cela a bien fonctionné jusqu'à un certain point, puis j'ai reçu un message d'erreur indiquant que la valeur a changé maintenant, avant c'était faux et maintenant c'est vrai. Il ne m'a pas donné d'autre explication que celle-ci.

2 votes

Si vous voulez parler d'une ExpressionChangedAfterItHasBeenCheckedError, cette erreur ne sera pas déclenchée en mode production.

0 votes

<child [data]="inputToChild"> </child> devrait probablement être <child [data]="(inputToChild)"> </child> pour obtenir des changements

69voto

Hardik Patel Points 17

Dans un composant parent, vous pouvez utiliser @ViewChild() pour accéder aux méthodes/variables du composant enfant.

@Component({
  selector: 'app-number-parent',
  templateUrl: './number-parent.component.html'
})
export class NumberParentComponent {
    @ViewChild(NumberComponent)
    private numberComponent: NumberComponent;
    increase() {
       this.numberComponent.increaseByOne();
    }
    decrease() {
       this.numberComponent.decreaseByOne();
    }
} 

Mise à jour :

Angular 8 et plus -

@ViewChild(NumberComponent, { static: false })

11 votes

Cela semble plus propre que de travailler avec des observables. L'inconvénient est que l'enfant doit être dans la vue. Si l'enfant est chargé avec le routage par exemple, cela échouera car numberComponent sera undefined .

4 votes

Est-ce une bonne pratique ? Je suis d'accord avec le fait que c'est plus propre que les observables, mais je doute de la manipulation des variables de l'enfant à partir du parent. Quoi qu'il en soit, cela a très bien fonctionné pour mes besoins, merci !

2 votes

C'est un bon conseil. On dirait que @ViewChild a changé dans Angular 8, ou du moins j'ai dû spécifier les options de la ViewChild. J'ai utilisé ceci dans mon cas : @ViewChild(Other, { static : false }) private otherComponent : Autre ;

11voto

Noki Points 136

Utilisez le décorateur @Input() dans votre composant enfant pour permettre au parent de se lier à cette entrée.

Dans le composant enfant, vous le déclarez tel quel :

@Input() myInputName: myType

Pour lier une propriété d'un parent à un enfant, vous devez ajouter dans votre modèle les crochets de liaison et le nom de votre entrée entre eux.

Exemple :

<my-child-component [myChildInputName]="myParentVar"></my-child-component>

Mais attention, les objets sont passés comme une référence, donc si l'objet est mis à jour dans l'enfant, la var du parent sera également mise à jour. Cela peut entraîner un comportement indésirable dans certains cas. Avec les types primaires, la valeur est copiée.

Pour aller plus loin, lisez ceci :

Docs : https://angular.io/docs/ts/latest/cookbook/component-communication.html

1voto

user2650368 Points 26

Dans le parent, vous pouvez faire référence à l'enfant en utilisant @ViewChild. En cas de besoin (c'est-à-dire lorsque l'événement est déclenché), vous pouvez simplement exécuter une méthode dans l'enfant à partir du parent en utilisant la référence @ViewChild.

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