2017-10-31 8 views
1

私は2つのフィールドを持っています。 1つは最小価格で、もう1つは最大価格です。私は最小値は常に最大値より小さくなければならず、最大値は最小値より大きくなければならないという検証をしたい。単純な肯定的なケースでは、正常に動作します。Angularの2つのフィールドの間の検証方法は?

しかし、一部のケースでは機能しません。

ユーザーが分で12、最大で100と入力したとします。ユーザーが123332を入力するか、または、何か大きな数字を入力すると、エラーメッセージが表示されます。

<div class="col-md-3" > 
<label for="minimumPriceTextbox" class="control-label">{{l("MinPrice")}}</label> 
<input type="text" 
     [minValue]="0" [maxValue]="test.maxPrice" 
     maxlength="17" class="form-control c" id="minimumPriceTextbox" 
     name="minimumPriceTextbox" 
     placeholder="Minimum Price" 
     [value]="test.minPrice" 
     [(ngModel)]="test.minPrice" 
     #minimumPriceTextbox="ngModel"> 
<div *ngIf="minimumPriceTextbox?.invalid && (minimumPriceTextbox?.dirty || minimumPriceTextbox?.touched)" class="has-error help-block help-block-error font-red-mint"> 
    <span> {{l("MinPriceShouldBeLessThanMaxPrice.")}} </span> 
</div> 
{{test.minPrice}} 
</div> 
<div class="col-md-3"> 
<label for="maximumPriceTextbox" class="control-label">{{l("MaxPrice")}}</label> 
<input name="maximumPriceTextbox" 
     type="text" 
     [minValue]="test.minPrice" 
     maxlength="17" class="form-control c" id="maximumPriceTextbox" 
     placeholder="Maximum Price" 
     [value]="test.maxPrice" 
     [(ngModel)]="test.maxPrice" 
     #maximumPriceTextbox="ngModel"> 
<div *ngIf="maximumPriceTextbox?.invalid && (maximumPriceTextbox?.dirty || maximumPriceTextbox?.touched)" class="has-error help-block help-block-error font-red-mint"> 
    <span> {{l("MaxPriceShouldBeGreaterThanMinPrice.")}} </span> 
</div> 
{{test.maxPrice}} 
</div> 

minValueディレクティブコード:

import { Directive, forwardRef, Attribute, Input } from '@angular/core'; 
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; 


@Directive({ 
    selector: '[minValue]', 
    providers: [ 
     { provide: NG_VALIDATORS, useExisting: forwardRef(() => MinValueValidator), multi: true } 
    ] 
}) 
export class MinValueValidator implements Validator { 

    @Input('minValue') minValue: number; 

    validate(control: AbstractControl): { [key: number]: any } { 
     let givenvalue = control.value; 
     let validationResult = null; 

     let minValue = this.minValue; 
     if (minValue && givenvalue < minValue) { 
      validationResult = validationResult || {}; 
      validationResult.minValue = true; 
     } 

     return validationResult; 
    } 
} 

maxValueディレクティブコード:

import { Directive, forwardRef, Attribute, Input } from '@angular/core'; 
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; 


@Directive({ 
    selector: '[maxValue]', 
    providers: [ 
     { provide: NG_VALIDATORS, useExisting: forwardRef(() => MaxValueValidator), multi: true } 
    ] 
}) 
export class MaxValueValidator implements Validator { 

    @Input('maxValue') maxValue: number; 

    validate(control: AbstractControl): { [key: number]: any } { 
     let givenvalue = control.value; 
     let validationResult = null; 

     let maxValue = this.maxValue; 
     if (maxValue && givenvalue > maxValue) { 
      validationResult = validationResult || {}; 
      validationResult.maxValue = true; 
     } 

     return validationResult; 
    } 
} 

答えて

0

相互検証を行うための簡単な方法はありませんが、しかし、独自に作成することが可能ですカスタム検証ディレクティブは、アイデアは、バリとバリデータ内のこれらの成分の変化を購読するフォームコンポーネント名を渡すことです:

export interface IValidatorFactory 
{ 
    (input:any, key:string):SyncValidatorResult; 
} 

@Directive({ 
    selector : 'input[sync]', 
    exportAs : 'sync', 
    providers: [{provide: NG_VALIDATORS, useExisting: forwardRef(() => GenericValidator), multi: true}] 
}) 
export class GenericValidator implements AsyncValidator, OnInit 
{ 
    @Input('sync') 
    public factory:IValidatorFactory; 

    @Input('deps') 
    public deps:string[]; 

    private onChange:() => void; 

    private readonly form:FormGroup; 

    constructor(form:NgForm) 
    { 
     this.form = form.form; 
    } 

    public ngOnInit():any 
    { 
     //wait for ngmodel created 
     setTimeout(() => 
     { 
      if(Array.isArray(this.deps) && this.deps.length > 0) 
      { 
       const values:any = Object.create(null); 

       for(const controlName of this.deps) 
       { 
        const control = this.form.get(controlName); 
        if(control == null) 
        { 
         console.error('Dependant control was not found', controlName); 
        } 
        else 
        { 
         control.valueChanges.subscribe(changes => 
         { 
          if(values[controlName] !== changes) 
          { 
           values[controlName] = changes; 
           this.onChange(); 
          } 
         }); 
        } 
       } 
      } 
     }, 0); 
    } 

    public registerOnValidatorChange(fn:() => void):void 
    { 
     this.onChange = fn; 
    } 

    public validate(c:AbstractControl):AsyncValidatorResult; 
    public validate(c:AbstractControl):SyncValidatorResult 
    { 
     return this.validatorFn(c); 
    } 

    private validatorFn(formControl:AbstractControl):SyncValidatorResult 
    { 
     if(formControl.value != null && this.factory != null) 
     { 
      return this.factory(formControl.value, 'syncValidator'); 
     } 
     return null; 
    } 
} 

    public onValidate(c:AbstractControl):ValidatorResult 
    { 
     return this.validatorFn(c); 
    } 

    private validatorFn(formControl:AbstractControl):SyncValidatorResult 
    { 
     if(formControl.value != null && this.factory != null) 
     { 
      return this.factory(formControl.value, 'syncValidator'); 
     } 
     return null; 
    } 
} 

テンプレート:

<input name="field1" type="text" [(ngModel)]="item.field1" [sync]="validateFields" [deps]="['field2']"></div> 
    <input name="field2" type="text" [(ngModel)]="item.field2" [sync]="validateFields" [deps]="['field1']"></div> 

コンポーネント:

public validateFields:IValidatorFactory = (value:string, key:string):SyncValidatorResult => 
{ 
    let result:SyncValidatorResult = null; 

    if(...) 
    { 
     result = Object.create(null); 
     result[key] = { 
      valid : false, 
      message: 'invalid values' 
     }; 
    } 
    return result; 
}; 
1

代わりディレクティブのは、簡単な関数を使用することはできませんか?あなたのTSで

<input type="number" (input)="checkValidity()" [(ngModel)]="maxValue"> 

(申し訳ありませんが、私は最小限にコードを削減します)ような何か:

checkValidity() { 
    if (this.maxValue < this.minValue) { /* Set your error here */ } 
    else if (this.minValue > this.maxValue) { /* Set your error here */ } 
    else { /* Set your other errors, or your validation here */ } 
} 
+0

私の目的は、フォームが唯一のエラーを表示するべきではないということです、それはあまりにも、フォームの妥当性を確認する必要があります。あなたのコードでは、エラーメッセージの表示のみを許可します。 –

+0

これは、リクエストしたとおり、2つのフィールドを比較する方法です。すべての入力(私はお勧めしませんが、あなたがそれを送信するときにのみ有効性をチェックする必要があります)全体フォームを検証する場合は、単に私の関数で、あなたの有効性チェックメソッドを呼び出すことができます! – trichetriche

+0

は完全にあなたに同意しますが、私はどのように角度でバリデーションメソッドを呼び出すのかわかりません? –

関連する問題