2016-01-25 68 views
15

我想要一個由標籤和文本框組成的模板。該模板可以在我的頁面的不同位置重複使用。要做到這一點,我已經創建了一個MyTextComponent。我想知道如何將不同的值綁定到組件輸入。Angular2數據綁定自定義可重用組件

例如:

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; 
} 

如何綁定MyTextComponent輸入的ngModel到MyPageComponent局部變量?

編輯: 加入@Output後試過,但它沒有工作:( 在MyPageComponent插值是空白的,以及日誌被打印未定義但是內插工作的mytextComponent任何想法

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); 
    } 
} 

回答

39

會將myText你缺少一個@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); 
    } 
} 

那麼你可以使用它像

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

謝謝!它確實有幫助。你知道嗎?在這種情況下,如何在MyTextComponent中傳遞附加函數時如何檢測MyPageComponent中的變化? – Alexey

+0

我想添加'ngOnChanges(){}'https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html是你正在尋找。它在@Input()的值改變時被調用。 –

+1

有什麼辦法使用'ngModel'作爲綁定輸入?例如''my-text [(ngModel)] =「person.name」>'帶'@Input()ngModel:string;' –

1

我覺得這個鏈接將回答你的問題。 http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

1 - 我的組件(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 - 然後你可以使用它像這樣

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