2017-01-04 19 views
16

子コンポーネントの要素の1つでCSSクラスをアクティブにするために、親コンポーネントからプロパティを受け取るために@inputを使用しています。子コンポーネントの親コンポーネントプロパティを角2で更新する

私は親からプロパティを受け取ることができ、また、クラスをアクティブにすることができます。しかしこれは一度しか働かない。私が親から受け取っているプロパティはブール型のデータであり、子コンポーネントからのステータスをfalseに設定すると、親では変更されません。

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

ヘッダ/ 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() { 

    } 
} 

上記のplunkerを確認してください。オープン検索機能は1回だけ機能します。検索を終了すると、再びトリガーされません。

@inputは、このシナリオの適切な使用例ですか?これを解決するのを手伝ってください。 (プランナーを更新してください)。

+0

ここで 'handleSearch()'で 'true'に設定された後、' this.isSearchActive = false; 'を設定していますか? –

+0

in header/search.ts '' – Body

答えて

38

2ウェイデータバインディングを使用する必要があります。

@Input()は片方向データバインディングです。あなたが親にあなたの財産への変更を公開する際、必要に2ウェイデータバインディング、プロパティに対応する@Output()を追加する必要があり、「変更」接尾辞

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

を有効にする 親に通知:

this.getSearchStatusChange.emit(newValue) 

や親に、あなたはそのプロパティのためにバナナ・イン・ザ・ボックスの表記を使用する必要があります。

[(getSearchStatus)]="myBoundProperty" 

あなたはまた、プロパティにバインドし、それが子供に変化したときにコールバックをトリガすることができます

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

plnkr

+0

ご回答いただきありがとうございます。私のプランナーを更新してもらえますか? – Body

+0

[plnkr](https://plnkr.co/edit/OTZLc7JSjog2DeI8WvKL?p=preview)で編集しました – n00dl3

+0

もう一度ありがとうございます。これはこのシナリオを処理する唯一の方法ですか?入出力コンボを使わずに他の方法がありますか? – Body

1

は、それが動作し、芋simplierに見える、少しあなたのコードを編集参照してください。あなたが好きなら教えてください。

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

+0

ありがとうございます。私は検索コンポーネントから親プロパティを更新したい。それは私の使用例です。 – Body

+0

@Body Fineですが、n00dl3ソリューションと一緒に、ボタンとクリック機構を変更した方法の使用を検討する必要があります。 –

+0

ありがとうございます。私はこの方法で使用します。 – Body

0

別のアプローチ:異なるコンポーネント間のステータスを渡すrxjs/BehaviorSubjectを使用します。
ここにはplunkrがあります。
件名に接尾辞 'Rxx'を付けると、searchStatusのBehaviorSubjectはsearchStatusRxxになります。

  1. は、子テンプレートで
  2. @Input
  3. を使用して、子コンポーネントへ
  4. パスそれは、あなたが非同期パイプを行い、searchStatusRxx = new BehaviorSubject(false);などの親コンポーネントでそれを初期化します。
  5. 親と子の両方で、最新の値を変更するにはsearchStatusRxx.next(value)を実行します。
1

さらに別の方法です。 Plunkr。私たちが望むのは、真実の単一の源です。私たちは今度は子供にそれを置くことができます。

  • 子で初期化:親テンプレートでsearchStatus = false
  • #asまたは任意の名前として、子のインスタンスを取得します。
  • 親のsearchStatusを#as.searchStatusと子供this.searchStatusを使用して変更します。
+0

この方法ははるかに優れており、簡単です。これは有効な方法ですか?なぜAngularはこのメソッドを宣伝していないのですか?私は一週間以来、私は入力/出力のケースを発見したすべてのソリューションを探しています。 – Body

+0

これを「テンプレート参照変数」の方法としましょう。それは単純なようです。しかし、テストするのが少し難しくなり、親子コンポーネントが一緒に結合していると良いことではないかもしれません。個人的には、BehaviorSubjectの方が好きです。テストとデカップリングが簡単で、親と子の間を通過する複雑なオブジェクトのプロパティとして設定できます。 sidenote:angleのeventEmitterは、背後にある主題です。 – Timathon