1

I have two dates input - "start date" and "end date" - I also have two directives in which I am using as validators - the allowed minimum and the allowed maximum value for each field (so that the start date won't be later from the end date). If for example I change the start date to be later than the end date, the validator will alert that it is not valid. when I change the end date to a later date from the start date - this alert will not disappear since I haven't triggered the "customMax" validator. how can I trigger both validators at once on every change in one of the fields?

Thanks,

inputs HTML:

<input
type="text" class="form-control"
name="startDate{{d.index}}"
required
[customMax]="d.endDate"
(dateChange)="onDateChange('startDate', d.index, $event)"
[(ngModel)]="d.startDate"
appMyDatePicker>
<input type="text" class="form-control"
required
[customMin]="d.startDate"
name="endDate{{d.index}}"
(dateChange)="onDateChange('endDate', d.index, $event)"
[(ngModel)]="d.endDate"
appMyDatePicker>

customMax directive:

@Directive({
selector: '[appCustomMaxValidator],[customMax][ngModel]',
providers: [{provide: NG_VALIDATORS, useExisting: 
CustomMaxValidatorDirective, multi: true}]
})
export class CustomMaxValidatorDirective implements Validator {

@Input()
customMax: Date;
constructor() { }

validate(c: FormControl): {[key: string]: any} {
const maxDateConvertInit = moment(this.customMax, 'DD/MM/YYYY HH:mm:ss').format('DD/MM/YYYY HH:mm:ss');
console.log('cant be greater than:' + maxDateConvertInit);
const maxDateConvertCompare = moment(c.value, 'DD/MM/YYYY HH:mm:ss').format('DD/MM/YYYY HH:mm:ss');
console.log('check date:' + maxDateConvertCompare);
const testScore = (maxDateConvertInit <= maxDateConvertCompare) ? {'customMax': true} : null;
return testScore;
}
}

customMin Directive:

@Directive({
  selector: '[appCustomMinValidator],[customMin][ngModel]',
  providers: [{provide: NG_VALIDATORS, useExisting: CustomMinValidatorDirective, multi: true}]
})
export class CustomMinValidatorDirective implements Validator {

  @Input()
  customMin: Date;
  constructor() { }

  validate(c: FormControl): {[key: string]: any} {
    const minDateConvertInit = moment(this.customMin, 'DD/MM/YYYY HH:mm:ss').format('DD/MM/YYYY HH:mm:ss');
    const minDateConvertCompare = moment(c.value, 'DD/MM/YYYY HH:mm:ss').format('DD/MM/YYYY HH:mm:ss');
    const testScore = (minDateConvertInit >= minDateConvertCompare) ? {'customMin': true} : null;
    return testScore;
  }

}

1 Answer 1

1

IMHO this should be handled by your component. You should trigger markAsTouched:

https://angular.io/api/forms/AbstractControl#markAsTouched

on both of the FormControls once one of them changes. This should force the validators to re-calculate. In my apps I use the following service:

import {Injectable, ChangeDetectorRef} from '@angular/core';
import {FormControl, NgForm} from '@angular/forms';

@Injectable()
export class FormService {

 constructor() {}

 public handleInvalidControls(form: NgForm, changeDetector: ChangeDetectorRef) {
    this.markInvalidControlsAsTouched(form);
    changeDetector.detectChanges();
 }

 private markInvalidControlsAsTouched(form: NgForm) {
     for (const key in form.form.controls) {
        const control = form.form.controls[key];
        if (control instanceof FormControl && control.invalid) {
           control.markAsTouched();
        }
     }
  }
}

In order to access your form from your component, you need to use Angulars ViewChild decorator in your template:

<form #submitForm="ngForm">

and in your component:

@Injectable()
export class FormComponent {

    @ViewChild('submitForm')
    submitForm;    
    ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

can you add your HTML template? I can't access my form tag from the ts file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.