2016-12-21 1 views
0

私は、formControlsである2つの日付/時刻選択コンポーネントを持つフォームを持つ親コンポーネントを持っています。これらはstartDateとendDateを表します。formControlの同時実行を行う方法

私はこれら2つのフォームコントロールで使用している2つのカスタムバリデータディレクティブも持っています。 1つは、入力Dateがコントロールの日付よりも小さいかどうかをチェックします。もう一方は、与えられた入力Dateがコントロールの日付よりも大きいかどうかをチェックします。

これら2つのバリは私がたstartDateとendDateにのために、以下の条件を検証することができます:

  1. たstartDateとendDateには(後に今よりも)将来でなければなりません
  2. たstartDateは、endDateに
前でなければなりません

私の問題は、日付の1つを更新すると、更新された日付にのみ検証が行われることです。例:

  1. 私はstartDateを有効な将来の日付に設定します。
  2. endDateをstartDateの前に設定しました。これにより、endDateが無効になります。
  3. endDateの前に有効な将来の日付にstartDateを変更します。 endDateが変更されたstartDateであっても、endDateが有効になることを期待しています。

私の質問は次のとおりです。どのようにエレガントに他のコントロールで有効にするか?親コンポーネントの

テンプレート:

<form #projectForm="ngForm" novalidate class="row"> 

    <div class="form-group col-md-6"> 
     <label for="startDate">Start Date</label> 
     <date-time-picker #startDate="ngModel" name="startDate" [(ngModel)]="project.startDate" [disabled]="isReadOnly" [dateLessThan]="project.endDate" [dateGreaterThan]="now"></date-time-picker> 
     <div *ngIf="startDate.errors"> 
     <div [hidden]="startDate.valid" *ngIf="startDate.errors.dateLessThan" class="alert alert-danger">Start date should be before end date</div> 
     <div [hidden]="startDate.valid" *ngIf="startDate.errors.dateGreaterThan" class="alert alert-danger">Date should be in the future</div> 
     </div> 
    </div> 

    <div class="form-group col-md-6"> 
     <label for="endDate">End Date</label> 
     <date-time-picker #endDate="ngModel" name="endDate" [(ngModel)]="project.endDate" [disabled]="isReadOnly" [dateGreaterThan]="maxDate()"></date-time-picker> 
     <div *ngIf="endDate.errors"> 
     <div [hidden]="endDate.valid" *ngIf="endDate.errors.dateGreaterThan" class="alert alert-danger">End date is too early</div> 
     </div> 
    </div> 
    </div> 
</div> 

日付少ないこと-validator.directive.ts:

import { Directive, forwardRef, Input } from '@angular/core'; 
import { NG_VALIDATORS, FormControl } from '@angular/forms'; 
import * as moment from 'moment'; 

/** 
* Directive to validate whether FormControl's date is less than input date 
*/ 
@Directive({ 
    selector: '[dateLessThan][ngModel],[dateLessThan][formControl]', 
    providers: [ 
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => DateLessThanValidatorDirective), multi: true } 
    ] 
}) 
export class DateLessThanValidatorDirective { 

    validator: Function; 

    constructor() { //If validating onEndDate, reverse the otherDate 
     this.validator = this.dateLessThan(); 
    } 

    @Input('dateLessThan') inputDate: Date; // Date comparing against. 

    validate(c: FormControl) { 
    return this.validator(c); 
    } 

    /** 
* Factory method that creates a function that accepts a form control. 
* Returns null if form is valid. Returns an object that contains error message if invalid. 
*/ 
    dateLessThan() { 
    return (c: FormControl) => { 

     let controlDate = c.value; 

     if (controlDate && this.inputDate) { //Only if both dates are set do we do validation 
     if (moment(controlDate).diff(this.inputDate) > 0) { 
      return { 
      dateLessThan: 'Controls date is greater than given date' 
      }; 
     } 
     } 
     return null; 
    }; 
    } 
} 

日付より大、validator.directive.ts :

import { Directive, forwardRef, Input } from '@angular/core'; 
import { NG_VALIDATORS, FormControl } from '@angular/forms'; 
import * as moment from 'moment'; 

/** 
* Directive to validate whether FormControl's date is greater than input date 
*/ 
@Directive({ 
    selector: '[dateGreaterThan][ngModel],[dateGreaterThan][formControl]', 
    providers: [ 
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => DateGreaterThanValidatorDirective), multi: true } 
    ] 
}) 
export class DateGreaterThanValidatorDirective { 

    validator: Function; 

    constructor() { //If validating onEndDate, reverse the otherDate 
     this.validator = this.dateGreaterThan(); 
    } 

    @Input('dateGreaterThan') inputDate: Date; // Date comparing against. 

    validate(c: FormControl) { 
    return this.validator(c); 
    } 

    /** 
* Factory method that creates a function that accepts a form control. 
* Returns null if form is valid. Returns an object that contains error message if invalid. 
*/ 
    dateGreaterThan() { 
    return (c: FormControl) => { 

     let controlDate = c.value; 

     if (controlDate && this.inputDate) { //Only if both dates are set do we do validation 
     if (moment(controlDate).diff(this.inputDate) < 0) { 
      return { 
      dateGreaterThan: 'Controls date is less than given date' 
      }; 
     } 
     } 

     return null; 
    }; 
    } 
} 

答えて

0

あなたが観察しているものはかなり期待されます。検証は、ユーザーの操作によって変更されているコントロールに対してのみトリガーされます。

あなたは次のようにシナリオに近づくことができる:

  • startDate|endDate用のカスタムバリデータを作成します。現在のformControlの値が将来のものであるかどうかだけを検証します。
  • formGroupのカスタムバリデータを作成し、startDate|endDateをラップします。このようにして、フィールドのいずれかが変更された場合、開始日が<であるかどうかを確認することができます。

2つのバリデータを実装することは、責任を明確に分けて、各バリデータのドメインロジックをカプセル化します。

これはあなたにとって理にかなっていると思います。

+0

しかし、コントロールの外の変数をバリデーターに渡しているときに、それらの変数の更新/変更について角度を探すべきではありませんか? – honestemu3

+0

私はそうは思わない。バリデーターは、一度に1つの日付時刻ピッカーのみに関連付けられます。 'ngModelGroup'を使用してグループの両方のバリデータを適用すると、いずれかのフィールドを変更すると両方が実行されます。 – rusev