2016-01-25 32 views
15

Desidero avere un modello costituito da un'etichetta e una casella di testo. Questo modello può essere riutilizzato in diversi punti della mia pagina. per farlo ho creato un MyTextComponent. Voglio sapere come associare valori diversi all'input dei componenti.Associazione dati angolare2 per componente riutilizzabile personalizzato

ad esempio:

MyTextComponent

import {Component, Input} from 'angular2/core'; 
@Component({ 
    selector: 'myText', 
    template:`<label>{{someLabel}}</label> 
       <input id=myId type="text" [(ngModel)]=bindModelData> 
       ` 
}) 
export class MyTextComponent { 
    @Input() myId : string; 
    @Input() bindModelData: any; 
} 

MyPageComponent

import {Component} from 'angular2/core'; 
import {MyTextComponent} from './MyTextComponent.component' 

@Component({ 
    template:`<myText myId="id1" bindModelData="myString1"></myText> 
       <myText myId="id2" bindModelData="myString2"></myText> 
       `, 
    directives:[MyTextComponent] 
}) 
export class MyPageComponent{ 
    myString1: string; 
    myString2: string; 
} 

Come posso legano ngModel dell'ingresso MyTextComponent per MyPageComponent variabile locale?

Edit: provato dopo aver aggiunto @Output, ma non ha funzionato :( l'interpolazione nel MyPageComponent è vuoto, così come il registro sta stampando indefinito Tuttavia l'interpolazione sta lavorando per la mytextComponent Tutte le idee

..
import {Component} from 'angular2/core'; 
import {MyTextComponent} from './myText.component' 

@Component({ 
    template:`<myText myId="id1" [(bindModelData)]="myString1"></myText> 
       <myText myId="id2" [(bindModelData)]="myString2"></myText> 
       {{myString1}} 
       {{myString2}} 

       <button (click)="clicked()">Click Me</button> 
       `, 
    directives:[MyTextComponent], 
    selector:'myPage' 
}) 
export class MyPageComponent{ 
    myString1: string; 
    myString2: string; 

    clicked(){ 
     console.log(this.myString1+'--'+this.myString2); 
    } 
} 


import {Component,Input,Output,EventEmitter} from 'angular2/core'; 
@Component({ 
    selector: 'myText', 
    template:`<label>{{someLabel}}</label> 
       <input id=myId type="text" [ngModel]=bindModelData (ngModelChange)="updateData($event)"> 
       modeldata - {{bindModelData}} 
       ` 
}) 
export class MyTextComponent { 
    @Input() myId : string; 
    @Input() bindModelData: any; 
    @Output() bindModelDataChanged: any = new EventEmitter(); 
    updateData(event) { 
     console.log('some random text'); 
     this.bindModelData = event; 
     this.bindModelDataChanged.emit(event); 
    } 
} 

risposta

39

tuo myText manca un @Output()

import {Component, Input, Output} from 'angular2/core'; 
@Component({ 
    selector: 'myText', 
    template:`<label>{{someLabel}}</label> 
       <input id=myId type="text" [ngModel]=bindModelData (ngModelChange)="updateData($event)"> 
       ` 
}) 
export class MyTextComponent { 
    @Input() myId : string; 
    @Input() bindModelData: any; 

    // note that this must be named as the input name + "Change" 
    @Output() bindModelDataChange: any = new EventEmitter();    

    updateData(event) { 
     this.bindModelData = event; 
     this.bindModelDataChange.emit(event); 
    } 
} 

quindi è possibile utilizzarlo come

import {Component} from 'angular2/core'; 
import {MyTextComponent} from './MyTextComponent.component' 

@Component({ 
    template:`<myText myId="id1" [(bindModelData)]="myString1"></myText> 
       <myText myId="id2" [(bindModelData)]="myString2"></myText> 
       `, 
    directives:[MyTextComponent] 
}) 
export class MyPageComponent{ 
    myString1: string; 
    myString2: string; 
} 

Plunker example

+0

Grazie! Aiuta davvero. Sai, come posso rilevare le modifiche in MyPageComponent in quel caso senza passare funzioni aggiuntive in MyTextComponent? – Alexey

+0

Suppongo che aggiungere 'ngOnChanges() {}' https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html sia quello che stai cercando. Viene chiamato quando cambia un valore '@Input()'. –

+1

C'è un modo per usare 'ngModel' come input associato? per esempio. '' con '@Input() ngModel: string;' –

1

Penso che questo link sarà rispondere alla tua domanda. http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

1- I miei componenti (tmg.input.ts)

import { Component, forwardRef , Input} from '@angular/core'; 
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; 

const noop =() => { 
}; 

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { 
    provide: NG_VALUE_ACCESSOR, 
    useExisting: forwardRef(() => TmgInput), 
    multi: true 
}; 

@Component({ 
    template: `<md-input-container> 
       <input mdInput id="id" name="name" placeholder="placeholder" [(ngModel)]="value" /> 
       </md-input-container>`, 
    selector: 'tmg-input', 
    templateUrl: './tmg.input.html', 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
}) 
export class TmgInput implements ControlValueAccessor { 

    @Input() id: string; 
    @Input() name: string; 
    @Input() placeholder: string; 

    //The internal data model 
    private innerValue: any = ''; 

    //Placeholders for the callbacks which are later providesd 
    //by the Control Value Accessor 
    private onTouchedCallback:() => void = noop; 
    private onChangeCallback: (_: any) => void = noop; 

    //get accessor 
    get value(): any { 
     return this.innerValue; 
    }; 

    //set accessor including call the onchange callback 
    set value(v: any) { 
     if (v !== this.innerValue) { 
      this.innerValue = v; 
      this.onChangeCallback(v); 
     } 
    } 

    //Set touched on blur 
    onBlur() { 
     this.onTouchedCallback(); 
    } 

    //From ControlValueAccessor interface 
    writeValue(value: any) { 
     if (value !== this.innerValue) { 
      this.innerValue = value; 
     } 
    } 

    //From ControlValueAccessor interface 
    registerOnChange(fn: any) { 
     this.onChangeCallback = fn; 
    } 

    //From ControlValueAccessor interface 
    registerOnTouched(fn: any) { 
     this.onTouchedCallback = fn; 
    } 

} 

2- Quindi è possibile utilizzare in questo modo

<tmg-input [id]="'test'" [name]="'test'" [placeholder]="'Test'" [(ngModel)]="model.test"></tmg-input> 
Problemi correlati