2016-01-05 18 views
8

Sto cercando di far funzionare qualcosa su angular2 e non riesco a trovare qualcosa su questo comportamento.Associazione dati bidirezionale su una proprietà di input componente

Ho un'applicazione che implementa un componente personalizzato come questo:

import {Component,Input} from 'angular2/core' 
    @Component({ 
     selector:'my-comp', 
     template:`<input type="text" style="text-align:center; [(ngModel)]="inputText"> <p>{{inputText}}</p>` 
    }) 

    export class MyComp{ 
     @Input() inputText : string; 
    } 

E io sto cercando di fare un'associazione dati bidirezionale sulla mia variabile inputText dalla mia componente in questo modo:

<my-comp [(inputText)]="testString"></my-comp> 

Dove testString è una variabile definita nello MyApp.ts che contiene una stringa. Voglio che la mia variabile testString venga modificata quando il mio inputText viene modificato dall'utente.

Ecco un Plunker con un codice di esempio semplice: https://plnkr.co/edit/zQiCQ3hxSSjCmhWJMJph?p=preview

C'è un modo per rendere questo funziona semplicemente? Devo implementare una classe Angular2 sui componenti personalizzati e sulle funzioni di sovraccarico per far sì che funzioni come un ngModel? Faccio necessariamente dover creare una variabile inputTextChanged di EventEmitter tipo che emettono i miei dati quando è cambiato e fare qualcosa del genere:

<my-comp [inputText]="testString" (inputTextChanged)="testString = $event;"></my-comp> 

Grazie in anticipo.

+2

Sì, è necessario creare un emettitore di eventi "inputTextChanged" e attivare l'evento all'interno del componente. Quindi [(inputText)] dovrebbe funzionare come previsto. – pixelbits

+0

Come avviso: non esiste un collegamento dati bidirezionale in Angular2, ma è possibile avere un comportamento simile. http://victorsavkin.com/post/110170125256/change-detection-in-angular-2 – jornare

+0

Bene secondo il Cheat Sheet Angular2 dal sito ufficiale: " \t Imposta il collegamento dati bidirezionale Equivalente a: ". Quindi penso che possiamo dire che ci sono dati bidirezionali vincolanti in Angular2. –

risposta

14

questo è spiegato nel documento modello di sintassi, nella sezione Two-Way Binding with NgModel:

<input [(ngModel)]="currentHero.firstName">

Internamente, angolare mappe del termine, ngModel, ad una proprietà di input ngModel e una proprietà ngModelChange uscita. Questo è un esempio specifico di uno schema più generale in cui corrisponde a [(x)] a una proprietà di input x per il binding di proprietà e una proprietà di output xChange per il binding di eventi.

Possiamo scrivere la nostra direttiva/componente di bind a doppio senso che segue questo modello se non avremo mai voglia di farlo.

Si noti anche che [(x)] è solo zucchero sintattico per una proprietà di legame e un evento di legame:

[x]="someParentProperty" (xChange)="someParentProperty=$event" 

Nel tuo caso, si vuole

<my-comp [(inputText)]="testString"></my-comp> 

così il componente deve avere un inputText proprietà di input e una proprietà di output inputTextChange (che è un EventEmitter).

export class MyComp { 
    @Input() inputText: string; 
    @Output() inputTextChange: EventEmitter<string> = new EventEmitter(); 
} 

di notificare alla madre di cambiamenti, ogni volta che il componente modifica il valore di inputText, emettono un evento:

inputTextChange.emit(newValue); 

nello scenario, il componente Mycomp lega proprietà di input inputText utilizzando il [(x)] in formato ngModel, quindi è stato utilizzato il bind evento (ngModelChange) per ricevere una notifica delle modifiche e in tale gestore eventi è stato notificato il componente principale della modifica.

In altri scenari in cui non è utilizzato ngModel, la cosa importante è emit() un evento ogni volta che il valore della proprietà inputText cambia nel componente MyComp.

+0

Aggiornamento Angular4: nel componente figlio non è più necessario specificare l'output EventEmitter. Questo viene gestito automaticamente da @input. vista principale: Bambino componente: export class Mycomp { @Input() inputText: string; } – switch87

1

Il Plunker contiene già lo EventEmitter. Manca l'annotazione @Output(). Per cambiare il valore chiamare inputTextChanged.emit(newValue) (questo cambia anche il valore su inputText)

+0

Sì, mi dispiace, sono nuovo di Plunker e ho dimenticato di bloccare il plunker allo stato che volevo che tu vedessi e ha continuato il mio test su di esso in modo che tu vedessi le mie modifiche. –

+0

Ho appena ricordato e non so se lo sai ma almeno dalla versione beta di Angular2 ".next()" è deprecato e dovresti usare ".emit()". –

+0

Grazie! non l'ho visto –

6

Combinerò @pixelbits e @ Günter Zöchbauer risposte e commenti per dare una risposta chiara alla mia domanda se qualcuno in futuro la sta cercando.

Per rendere il bind di dati bidirezionale funzioni su variabili personalizzate è necessario creare il componente in base a quanto segue. il file

MyComp.ts:

import {Component,Input,Output,EventEmitter} from 'angular2/core' 
@Component({ 
    selector:'my-comp', 
    templateUrl:`<input type="text" style="text-align:center;" 
    [ngModel]="inputText" (ngModelChange)="inputText=$event;inputTextChange.emit($event);">` 
}) 

export class MyComp{ 
    @Input() inputText : string; 
    @Output() inputTextChange = new EventEmitter(); 
} 

MyApp.ts di file:

import {Component} from 'angular2/core' 
import {MyComp} from './MyComp' 

@Component({ 
    selector:'my-app', 
    templateUrl:`<h1>Bidirectionnal Binding test </h1> 
    <my-comp [(inputText)]="testString"></my-comp><p> 
    <b>My Test String :</b> {{testString}}</p>`, 
    directives:[MyComp] 
}) 

export class MyApp{ 
    testString : string; 
    constructor(){ 
    this.testString = "This is a test string"; 
    } 
} 

Ci i dati bidirezionali associazione alla variabile inputText funziona correttamente. Puoi commentare la risposta per un modo più bello o più semplice per implementare questo codice.