2016-07-19 19 views
13

Tôi có thành phần đầu vào tùy chỉnh đang cập nhật xác thực và nêu rõ ngoại lệ bị chạm/không chạm. Mọi thứ khác nhà nước-khôn ngoan (nguyên sơ/bẩn) hoạt động như mong đợi.chạm/không chạm vào không cập nhật trong thành phần đầu vào tùy chỉnh - Góc 2

Dưới đây là một 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; 
    } 

} 

Nhờ sự giúp đỡ!

Trả lời

8

Chỉ cần bước vào câu trả lời @sharpmachine và nó đã góp phần giải quyết vấn đề của tôi. Tôi chỉ muốn cải thiện nó:

Thay vì phải để ràng buộc sự kiện blur-onTouched() tại mẫu mực (có thể dễ bị lỗi) nó có thể để lộ những ControlValueAccessor như một Directive và ràng buộc sự kiện đó.

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

Bằng cách này bạn sẽ có thể sử dụng thành phần này mà không phải ràng buộc sự kiện blur mỗi khi bạn sử dụng.

Hy vọng điều đó sẽ hữu ích!

+0

Cảm ơn! Rất hữu ích! – sharpmachine

4

Tôi đã phạm hai sai lầm, như một nút bấm. Vì vậy, các mẫu cần phải được:

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

Vì vậy, hai điều mà (blur)="onTouched($event)" trên đầu vào, và <p *ngIf="control?.errors?.required && control?.touched">

+0

Tất nhiên! Đối với một số lý do tôi mặc dù thực hiện giao diện ControlValueAccessor sẽ giải quyết điều đó cho tôi. Ehh. – lukeatdesignworks

Các vấn đề liên quan