2016-07-19 3 views
13

У меня есть пользовательский компонент ввода, который обновляет валидацию и состояния, за исключением коснутых/нетронутых. Все остальное по-государственному (первозданному/грязному) работает так, как ожидалось.коснулся/нетронутый, не обновлялся в пользовательском компоненте ввода - Угловой 2

Вот 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; 
    } 

} 

Спасибо за любую помощь!

ответ

8

Просто ступенчатые на @sharpmachine ответ, и это помогло решить мою проблему. Я просто хотел бы улучшить:

Вместо того, чтобы связать blur событие onTouched() на уровне шаблона (который может быть подвержен ошибкам) ​​можно подвергать ControlValueAccessor как Directive и связать событие там.

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

Таким образом, вы должны быть в состоянии использовать компонент без необходимости, чтобы связать blur события каждый раз, когда вы используете его.

Надеюсь, это поможет!

+0

Спасибо! Очень полезно! – sharpmachine

4

Я делал две ошибки, как рукоятка. Таким образом, шаблон должен быть:

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

Так две вещи, где (blur)="onTouched($event)" на входе и <p *ngIf="control?.errors?.required && control?.touched">

+0

Конечно! По какой-то причине я уверен, что реализация интерфейса ControlValueAccessor решит это для меня. Эхх. – lukeatdesignworks

Смежные вопросы