I have stuck in a situation where I have to remove the invalid state of a control based on the other control. I have 2 date picker controls "StartDate" and "EndDate". Here validation are applied as
Startdate should be less than equal to Enddate
EndDate should be greater than equal Startdate
validation message appear as expected The problem arises when both the validation fail and when I try to make a date equal to other the other control validation should also trigger. For validation i have implemented a CustomValidatorDirective
/**
* Class which provide validation functionalities
*/
export class CustomValidatorDirective implements Validator {
@Input('validations') validations: Array<Object> = [];
@Input('fields') fields: Array<Object> = [];
validator: ValidatorFn;
constructor(private translate: TranslateService) { }
validate(control: AbstractControl): { [key: string]: any } {
const isValid = false;
return this.Validate(control, control.value);
}
/**
* A function which do custom validation for the control
*/
Validate(control: AbstractControl, value): { [key: string]: any } {
let validators = []
validators = _.chain(this.validations).values().pluck('Key').value();
const message = '';
if (_.contains(validators, 'Gte')) {
const label = _.findWhere(this.validations, {Key: 'Gte'})['Value'];
if (value && value < control.parent.controls[label.toString()].value){
return { 'Gte': { valid: false, message: 'Validations.GREATER_THAN_EQUAL', data: label } };
} else if (control.parent.controls[label.toString()]!== undefined && control.parent.controls[label.toString()].dirty && value && value >= control.parent.controls[label.toString()].value){
control.parent.controls[label.toString()].errors=[];
}
}
if (_.contains(validators, 'Lte')) {
const label = _.findWhere(this.validations, {Key: 'Lte'})['Value'];
if (value && value > control.parent.controls[label.toString()].value){//this.fields[index]['Value'] ) {
return { 'Lte': { valid: false, message: 'Validations.LESS_THAN_EQUAL', data: label } };
} else if (control.parent.controls[label.toString()]!== undefined && control.parent.controls[label.toString()].dirty && value && value <= control.parent.controls[label.toString()].value){
control.parent.controls[label.toString()].errors=[];
}
}
<form #dynamicform="ngForm" (ngSubmit)="onSubmit(dynamicform.value, dynamicform)">
<div *ngIf="isDropDownDataLoading" class="dynamic-loader-section" appSetHeight [offset]="305" [property]="'line-height'">
<img src="./assets/images/loader.gif" />
</div>
<div class="accordion" *ngFor="let key of keys(data);let $index = index">
<mat-accordion>
<mat-expansion-panel class="custom-expansion-panel" [expanded]="true" hideToggle="false">
<mat-expansion-panel-header expandedHeight="48px">
<!-- <mat-panel-title>{{key === 'null'? ('CONFIGURATION_MANAGER.DYNAMIC_GENERAL' | translate): key}}</mat-panel-title> -->
<mat-panel-title>{{key === 'null'? 'General': key}}</mat-panel-title>
</mat-expansion-panel-header>
<mat-panel-description>
<div class="container no-pad no-margin full-width">
<div class="row no-pad no-margin" *ngFor="let chunk of data[key];let last = last">
<div class="col-4 no-pad no-margin height-50"
[ngClass] = "{'col-12':(field?.EditorKind == 'Dictonary'),'height-35':(field?.EditorKind == 'DropDownList' || field?.EditorKind == 'MultiSelect')}"
*ngFor="let field of chunk">
<div class="form-field-container" [ngSwitch]="field?.EditorKind">
<mat-form-field *ngSwitchCase="'Email'">
<input matInput [placeholder]="field['Label']" [(ngModel)]="field['Value']" [name]="field.Key" [readonly]="field['ReadOnly'] || !hasPermission"
appCustomValidator [validations]="field.Validations" autocomplete="off"/>
<mat-error *ngIf="dynamicform?.invalid && dynamicform.controls[(field.Key).toString()]?.invalid">
{{ (dynamicform.controls[(field.Key).toString()]?.errors.Required?.message | translate) ||
(dynamicform.controls[(field.Key).toString()]?.errors.Email?.message | translate)}}
</mat-error>
</mat-form-field>
<mat-form-field *ngSwitchCase="'Date'">
<input matInput [matDatepicker]="picker1" [placeholder]="field['Label']" [(ngModel)]="field['Value']" [name]="field.Key" autocomplete="off"
appCustomValidator [validations]="field.Validations" [fields]="chunk" [disabled]="field['ReadOnly'] || !hasPermission" >
<mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
<mat-datepicker #picker1></mat-datepicker>
<mat-error *ngIf="dynamicform?.invalid && dynamicform.controls[(field.Key).toString()]?.invalid ">
{{(dynamicform.controls[(field.Key).toString()]?.errors.Required?.message| translate)||
(dynamicform.controls[(field.Key).toString()]?.errors.Gte?.message | translate:{'1': dynamicform.controls[(field.Key).toString()]?.errors.Gte?.data})||
(dynamicform.controls[(field.Key).toString()]?.errors.Lte?.message | translate:{'1': dynamicform.controls[(field.Key).toString()]?.errors.Lte?.data})||}}
</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div>
</mat-panel-description>
</mat-expansion-panel>
</mat-accordion>
</div>
</form>