web-dev-qa-db-fra.com

Mettre à jour la propriété du composant parent à partir du composant enfant dans Angular 2

J'utilise @input pour recevoir une propriété du composant parent afin d'activer une classe CSS dans l'un des éléments du composant enfant.

Je peux recevoir la propriété du parent et aussi activer la classe. Mais cela ne fonctionne qu'une fois. La propriété que je reçois de parent est une donnée booléenne typée et lorsque je règle son statut sur false à partir du composant enfant, elle ne change pas dans parent.

Plunkr: https://plnkr.co/edit/58xuZ1uzvToPhPtOING2?p=preview

app.ts

import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { HeaderComponent } from './header';
import { SearchComponent } from './header/search';

@Component({
  selector: 'my-app',
  template: `
    <app-header></app-header>
  `,
})
export class App {
  name:string;
  constructor() {
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, HeaderComponent, SearchComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

header.ts

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

@Component({
  selector: 'app-header',
  template: `<header>
              <app-search [getSearchStatus]="isSearchActive"></app-search>
              <button (click)="handleSearch()">Open Search</button>
            </header>`
})
export class HeaderComponent implements OnInit {
  isSearchActive = false;

  handleSearch() {
    this.isSearchActive = true
    console.log(this.isSearchActive)
  }

  constructor() { }
  ngOnInit() { }
}

header/search.ts

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

@Component({
  selector: 'app-search',
  template: `<div id="search" [class.toggled]="getSearchStatus">
              search 
              <button  (click)="getSearchStatus = false" class="close">Close Search</button>
            </div>`
})
export class SearchComponent implements OnInit {
  @Input() getSearchStatus: boolean;

  constructor() { }

  ngOnInit() {

  }
}

S'il vous plaît vérifier le plunker donné ci-dessus. La fonction de recherche ouverte ne fonctionne qu'une fois. Après la fermeture de la recherche, il ne se déclenche plus.

Est-ce que @input est le cas d'utilisation approprié pour ce scénario? S'il vous plaît aidez-moi à résoudre ce problème. (S'il vous plaît mettre à jour le plunker).

55
Body

Vous devez utiliser une liaison de données bidirectionnelle.

@Input() est une liaison de données à sens unique. pour activer la liaison de données bidirectionnelle, vous devez ajouter un @Output() correspondant à la propriété, avec le suffixe "Modifier"

@Input() getSearchStatus: boolean;
@Output() getSearchStatusChange = new EventEmitter<boolean>();

lorsque vous souhaitez publier la modification apportée à votre propriété sur le parent, vous devez en informer le parent avec:

this.getSearchStatusChange.emit(newValue)

et dans le parent, vous devez utiliser la notation banane dans une boîte pour cette propriété:

[(getSearchStatus)]="myBoundProperty"

vous pouvez également vous lier à la propriété et déclencher un rappel lorsqu'il change dans child:

[getSearchStatus]="myBoundProperty" (getSearchStatusChange)="myCrazyCallback($event)"

voir le plnkr

102
n00dl3

Une autre approche: utilisez rxjs/BehaviorSubject pour transmettre le statut entre différents composants.
Voici le plunkr .
Je nomme sujet avec le suffixe 'Rxx', le BehaviorSubject pour searchStatus sera donc searchStatusRxx.

  1. l'initialiser dans le composant parent comme searchStatusRxx = new BehaviorSubject(false);,
  2. transmettez-le au composant enfant à l'aide de @Input
  3. dans le gabarit enfant, vous faites pipe async.
  4. à la fois dans parent et enfant, vous faites searchStatusRxx.next(value) pour changer la dernière valeur.
4
Timathon

Edité votre code un peu, cela fonctionne et semble plus simple imo. Dis-moi si ça te plait.

https://plnkr.co/edit/oJOjEZfAfx8iKZmzB3NY?p=preview

3
kind user

Encore une autre façon. Plunkr . Ce que nous voulons, c'est une source unique de vérité. Nous pouvons mettre cela dans l'enfant cette fois.

  • Init in child: searchStatus = false
  • Dans le modèle parent, obtenez l'instance de l'enfant sous la forme #as ou quel que soit son nom.
  • Modifiez searchStatus dans parent en utilisant #as.searchStatus et dans enfant this.searchStatus.
2
Timathon