web-dev-qa-db-ja.com

カスタムの再利用可能なコンポーネントのAngular2データバインディング

ラベルとテキストボックスで構成されるテンプレートが欲しいのですが。このテンプレートは、ページのさまざまな場所で再利用できます。そのために、MyTextComponentを作成しました。さまざまな値をコンポーネント入力にバインドする方法を知りたいです。

例えば:

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);
    }
}
17
vikash kaushik

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の例

39

このリンクがあなたの質問に答えると思います。 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>
1
Mohammad Karimi