2017-01-04 3 views
16

Ich verwende @input, um eine Eigenschaft von Elternkomponente zu erhalten, um eine CSS-Klasse in einem Element der Kindkomponente zu aktivieren.Aktualisiere Parent-Komponente-Eigenschaft von Kind-Komponente in Angular 2

Ich bin in der Lage, die Eigenschaft von Eltern zu erhalten und auch die Klasse zu aktivieren. Aber das funktioniert nur einmal. Die Eigenschaft, die ich von Parent erhalte, ist ein boolescher Datentyp, und wenn ich den Status davon auf false von einer untergeordneten Komponente aus einstelle, ändert sie sich nicht im übergeordneten Element.

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() { 

    } 
} 

Bitte überprüfen Sie den oben angegebenen Kolben. Die offene Suche funktioniert nur einmal. Nach dem Schließen der Suche wird es nicht erneut ausgelöst.

Ist @input der richtige Anwendungsfall für dieses Szenario? Bitte helfen Sie mir, das zu beheben. (Bitte aktualisieren Sie den Plocker).

+0

Wo setzen Sie 'this.isSearchActive = false;' nachdem es in 'handleSearch()' auf 'true' gesetzt wurde? –

+0

in header/search.ts '

Antwort

38

Sie müssen eine 2-Wege-Datenbindung verwenden.

@Input() ist One-Way-Datenbindung. ermöglichen, 2-Wege-Datenbindungs ​​Sie eine @Output() entsprechend der Eigenschaft hinzufügen müssen, mit einem „Change“ Suffix

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

, wenn Sie die Änderung vorgenommen hat, um Ihr Eigentum zu übergeordneten veröffentlichen möchten, müssen Sie benachrichtigen die Eltern mit:

this.getSearchStatusChange.emit(newValue) 

und in der Mutter müssen Sie für diese Eigenschaft die Banane-in-a-Box-Notation verwenden:

[(getSearchStatus)]="myBoundProperty" 

Sie können auch auf die Eigenschaft binden und einen Rückruf auslösen, wenn es in der Kinder ändert:

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

sehen die plnkr

+0

Vielen Dank für Ihre Antwort. Kannst du bitte meinen Plunker aktualisieren? – Body

+0

Ich bearbeitet mit einem [PLNKR] (https://plnkr.co/edit/OTZLc7JSjog2DeI8WvKL?p=preview) – n00dl3

+0

Vielen Dank noch einmal. Ist das die einzige Möglichkeit, mit diesem Szenario umzugehen? Gibt es noch andere Möglichkeiten ohne Eingabe/Ausgabe-Kombination? – Body

1

Ihren Code ein wenig Edited, es funktioniert und sieht simplier imo. Sag mir, ob Du es magst.

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

+0

Danke. Ich möchte die übergeordnete Eigenschaft von der Suchkomponente aktualisieren. Das ist mein Anwendungsfall. – Body

+0

@Body Fein, aber Sie sollten in Betracht ziehen, wie ich Ihre Tasten und Klick-Mechanismus zusammen mit n00dl3 Lösung geändert haben. –

+0

Danke. Ich werde diesen Weg benutzen. – Body

0

Ein anderer Ansatz: Verwendung rxjs/BehaviorSubject Status zwischen den verschiedenen Komponenten zu übergeben.
Hier ist die plunkr.
Ich benenne Betreff mit einem Suffix 'Rxx', so dass das BehaviorSubject für searchStatus searchStatusRxx ist.

  1. initialisieren es in übergeordnete Komponente wie searchStatusRxx = new BehaviorSubject(false);,
  2. Pass es Komponente Kind @Input Vorlage
  3. in Kind verwenden, können Sie async Rohr tun.
  4. in Eltern und Kind, tun Sie searchStatusRxx.next(value), um den neuesten Wert zu ändern.
1

Noch ein anderer Weg. Plunkr. Was wir wollen, ist eine einzige Quelle der Wahrheit. Das können wir diesmal in ein Kind legen.

  • Init in Kind: searchStatus = false
  • In allen Templates erhalten die Instanz des Kindes als #as oder was auch immer Namen.
  • Ändern Sie searchStatus in Parent mit #as.searchStatus und in Kind this.searchStatus.
+0

Dieser Weg ist viel besser und einfacher. Ist das ein gültiger Weg? Warum fördert Angular diese Methode nicht? Ich suche seit einer Woche nach einer Lösung und überall fand ich Eingabe-/Ausgabefälle. – Body

+0

Lassen Sie uns dies als "Vorlage Referenzvariablen" -Weise nennen. Es scheint einfach zu sein. Aber es kann ein bisschen schwieriger zu testen sein und die Eltern/Kind-Komponenten sind miteinander verbunden, was vielleicht keine gute Sache ist. Persönlich bevorzuge ich die BehaviorSubject-Methode, die einfacher zu testen und zu entkoppeln ist und als eine Eigenschaft für die Übergabe komplexer Objekte zwischen Eltern und Kind festgelegt werden kann. Eine Nebenbemerkung: EventEmitter von eckle ist ein Thema hinter den Kulissen. – Timathon

Verwandte Themen