2016-08-11 17 views
3

現在、Angular 2 RC4と新しいフォームAPIを使用してかなり長いフォームを開発しています。角2のカスタム入力コンポーネントの検証(新しいフォームapi)

私は自分の入力コンポーネントを持っており、検証を処理するために一歩進んでいきたいと考えています。

は、私は私の入力での作業私のバリデータを持ってしようとしていますが、バリデータではなく、私の入力フィールドのコンポーネントInputFieldComponentを更新...ここ

は私のhtmlです:

によって呼び出さ
<label [attr.for]="inputId"><ng-content></ng-content></label> 
<small class="text-muted">{{helptext}}</small> 
<small [hidden]="(input.valid) || (input.untouched && input.pristine)" class="text-danger"> 
    {{errormsg}} 
</small> 
<input 
     class="form-control custom-input" 
     [id]="inputId" 
     [required]="required" 
     [type]="type" 
     [attr.name]="name" 
     [(ngModel)]="value" 
     [pattern]="pattern" 
     #input="ngModel" 
     > 

ここで

<custom-input-field 
    name="birthDate" 
    [(ngModel)]="model.birthDate" 
    placeholder="DD/MM/YYYY" 
    helptext="Date of birth" 
    required="true" 
    pattern="^[0-3]?[0-9]\/[01]?[0-9]\/[12][90][0-9][0-9]$" 
    errormsg="The date of birth is mandatory and should be entered as dd/mm/yyyy" 
> 
    Date of birth 

</custom-input-field> 

は私のコードです:

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

const noop =() => {}; 

let nextUniqueId = 0; 

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

@Component({ 
    moduleId: module.id, 
    selector: 'custom-input-field', 
    styleUrls: ['input-field.component.css'], 
    templateUrl: 'input-field.component.html', 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
}) 


export class InputFieldComponent implements ControlValueAccessor { 
    //the external properties 
    @Input() id: string = `custom-field-${nextUniqueId++}`; 
    @Input() helptext: string = null; 
    @Input() placeholder: string = null; 
    @Input() required: boolean = false; 
    @Input() type: string = 'text'; 
    @Input() name: string = null; 

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

    //Placeholders for the callbacks which are later provided 
    //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); 
    } 
    } 

    //From ControlValueAccessor interface 
    // The writeValue function allows you to update your internal model with incoming values, 
    // for example if you use ngModel to bind your control to data. 
    writeValue(value: any) { 
    if (value !== this.innerValue) { 
     this.innerValue = value; 
    } 
    } 

    //NOTE: Both following functions are later provided by Angular 2 itself. But we need to register dummy functions to be 
    // able code and transpile it without errors. 

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

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

    //** Read-only properties */ 
    get inputId(): string { return `${this.id}-input`; } 
}; 

答えて

1

私は最終的に私が望むことを達成するための回避策を見つけました。

  • テンプレート変数が
  • 動的にすることはできませんし、私は私のコンポーネントのプロパティにアクセスして、ハードの時間を持っていたし、

Expression 'xxxx' was changed after it was checkedのような問題で)HTMLビューで動的にそれらの値をテストしているので最終的に、カスタムコンポーネントのシャドードームを使用して、コンポーネントが有効かどうかをテストし、動作し、コードをさらに軽くしました。ここ

は、そのCSSセレクタ

@Component({ 
    moduleId: module.id, 
    selector: 'custom-input-field', 
    templateUrl: 'input-field.component.html', 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR], 
    directives: [DefaultValueAccessor, NgModel], 
    host: { 
    '(click)': 'focus()', 
    '[class.custom-input]': 'true', 
    }, 

    /** 
    * This styles the input error msg that is integrated into our component using the automatic classes 
    * that ngModel updates on the component. 
    * 
    * It uses the shadow-dom and therefore has to be declared line by line in the component file 
    * (does not seem to work with Sass transpiler) 
    */ 
    styles: [ 
    ` 
    :host.ng-touched.ng-invalid >>> input { 
     border-left: 5px solid #a94442; /* red */ 
    } 

    :host.ng-touched.ng-valid >>> input { 
     border-left: 5px solid #42A948; /* green */ 
    } 

    :host.ng-valid:not([required]).ng-touched.ng-dirty >>> input { 
     border-left: 5px solid #42A948; /* green */ 
    } 

    :host.ng-pristine >>> .error-msg { 
     display:none; 
    } 

    :host.ng-valid >>> .error-msg { 
     display:none; 
    } 

    :host.ng-untouched >>> .error-msg { 
     display:none; 
    } 

    :host.ng-touched.ng-invalid >>> .error-msg { 
     display:inline; 
    } 

    .text-danger { font-weight: 500; } 
} 
    `] 
}) 

を持つ私のカスタム入力コンポーネントのコードであり、ここで(複数のプロパティの濃縮)テンプレートコンテンツです:私のような私のコンポーネントを呼び出す

<label [attr.for]="inputId"><ng-content></ng-content></label> 
<small class="text-muted">{{helptext}}</small> 
<small class="error-msg text-danger"> 
    <ng-content select="input-error"></ng-content> 
</small> 

<input #input 
     class="form-control custom-input" 
     [disabled]="disabled" 
     [id]="inputId" 
     [attr.list]="list" 
     [attr.max]="max" 
     [attr.maxlength]="maxLength" 
     [attr.min]="min" 
     [attr.minlength]="minLength" 
     [readonly]="readOnly" 
     [required]="required" 
     [spellcheck]="spellCheck" 
     [attr.step]="step" 
     [attr.tabindex]="tabIndex" 
     [type]="type" 
     [attr.name]="name" 
     (focus)="_handleFocus($event)" 
     (blur)="_handleBlur($event)" 
     (change)="_handleChange($event)" 
     [(ngModel)]="value" 
> 

<custom-input-field 
       name="birthDate" 
       [(ngModel)]="model.birthDate" 
       placeholder="JJ/MM/AAAA" 
       helptext="format jj/mm/aaaa" 
       #birthDate="ngModel" 
       required="true" 
       pattern="^[0-3]?[0-9]\/[01]?[0-9]\/[12][90][0-9][0-9]$" 
      > 
       Date of birth 
       <input-error><br />The date of birth is mandatory and should be entered as dd/mm/yyyy</input-error> 
      </custom-input-field> 
関連する問題