2016-07-19 6 views
13

Ich habe eine benutzerdefinierte Eingabekomponente, die Validierung und Zustände mit Ausnahme von berührt/unberührt aktualisiert. Alles andere state-weise (makellos/schmutzig) funktioniert wie erwartet.berührte/unberührte nicht in benutzerdefinierten Eingangskomponente aktualisieren - Angular 2

Hier ist ein Plunker: https://plnkr.co/edit/O9KWzwhjvySnXd7vyo71

import { Component, OnInit, Input, ElementRef, forwardRef, Renderer } from '@angular/core'; 
import { REACTIVE_FORM_DIRECTIVES, Validator, Validators, NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; 



export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = /*@ts2dart_const*/ { 
    provide: NG_VALUE_ACCESSOR, 
    useExisting: forwardRef(() => CustomInputComponent), 
    multi: true 
}; 

const noop =() => {}; 

@Component({ 
    selector: 'my-custom-input', 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR], 
    template: ` 
    <div class="form-group"> 
    <label>CUSTOM INPUT</label> 
    <input type="text" class="form-control" [(ngModel)]="value" required> 
    <p *ngIf="control.errors.required && control.touched">Field is required</p> 
    <strong>Has input been touched: {{control.touched ? 'Yes' : 'No'}}</strong><br> 
    <strong>Is input untouched: {{control.untouched ? 'Yes' : 'No'}}</strong><br> 
    <strong>Is input dirty: {{control.dirty ? 'Yes' : 'No'}}</strong> <br> 
     <strong>Is input pristine: {{control.pristine ? 'Yes' : 'No'}}</strong> 
    </div> 
    <div> 
    In Custom Component: {{value}} 
    </div> 
` 
}) 


export class CustomInputComponent implements ControlValueAccessor { 
    @Input() control; 


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

    //Placeholders for the callbacks 
    private _onTouchedCallback: (_:any) => void = noop; 

    private _onChangeCallback: (_:any) => void = noop; 

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

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

    //Set touched on blur 
    onTouched(){ 
    this._onTouchedCallback(null); 
    } 

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

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

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

} 

Vielen Dank für jede Hilfe!

Antwort

8

einfach auf @sharpmachine Antwort trat und es half, mein Problem zu lösen. Ich möchte nur, es verbessern:

Anstatt das blur Ereignis onTouched() auf Vorlagenebene zu binden (die fehleranfällig sein kann) ist es möglich, die ControlValueAccessor als Directive und bindet die Veranstaltung dort zu belichten.

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

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

@Directive({ 
    selector: 'my-custom-input', 
    host: {'(blur)': 'onTouched($event)'}, 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR], 
}) 
export class CustomInputAccessor implements ControlValueAccessor { 

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

    public onChange: any = (_) => { /*Empty*/ } 
    public onTouched: any =() => { /*Empty*/ } 

    get value(): any { return this._value; }; 

    set value(v: any) { 
    if (v !== this._value) { 
     this._value = v; 
     this.onChange(v); 
    } 
    } 

    writeValue(value: any) { 
    this._value = value; 
    } 

    registerOnChange(fn: any) { 
    this.onChange = fn; 
    } 

    registerOnTouched(fn: any) { 
    this.onTouched = fn; 
    } 
} 

Auf diese Weise sollten Sie die blur Ereignis jedes Mal, wenn Sie es verwenden zu binden, ohne die Komponente verwenden können.

Hoffe es hilft!

+0

Danke! Sehr hilfreich! – sharpmachine

4

Ich machte zwei Fehler, wie ein Knopfkopf. So muss die Vorlage sein:

<div class="form-group"> 
    <label>CUSTOM INPUT</label> 
    <input type="text" class="form-control" [(ngModel)]="value" (blur)="onTouched($event)" required> 
    <p *ngIf="control?.errors?.required && control?.touched">Field is required</p> 

    <strong>Has input been touched: {{control.touched ? 'Yes' : 'No'}}</strong><br> 
    <strong>Is input untouched: {{control.untouched ? 'Yes' : 'No'}}</strong><br> 
    <strong>Is input dirty: {{control.dirty ? 'Yes' : 'No'}}</strong> <br> 
    <strong>Is input pristine: {{control.pristine ? 'Yes' : 'No'}}</strong> 
    </div> 
    <div> 
    In Custom Component: {{value}} 
    </div> 

So sind die zwei Dinge, wo die (blur)="onTouched($event)" am Eingang und die <p *ngIf="control?.errors?.required && control?.touched">

+0

Natürlich! Aus irgendeinem Grund habe ich festgestellt, dass die Implementierung der ControlValueAccessor-Schnittstelle das für mich löst. Ehh. – lukeatdesignworks