I have an input field for selecting date. I want to apply simple validation that if this field is empty then the submit button should be disabled and enabled when it's filled and it shoud be in sync.
The date field is having some issue, when I checked through ng-valid it is supposed to give false when nothing is entered into the date field but it's giving true right from the word go.
I created a simple example using StackBlitz having a single input of date, now I need to disable it when input field is empty and activate it when input is filled.
CodePudding user response:
It is due to the poor implementation on the date picker part. By default, they set value of the control to {start: null, end: null}
. https://stackblitz.com/edit/ngx-daterangepicker-material-for-angular8-fa73zq?file=src/app/app.component.html
The default required
validator checks if the controlValue == null
and the object that is set to the control by library is not null-ish. In case if you need to use this library, you need to write your custom validator that would check if both start
and end
are null and if so it should return an error.
You check how to do it here: https://angular.io/guide/form-validation#adding-custom-validators-to-template-driven-forms
CodePudding user response:
By default, when your input date is empty its value is { "start": null, "end": null }
. So the "required" validator does not invalidate the value, because this is a valid object.
A simple way to fix:
<button
[disabled]="!(date.value.start && date.value.end)"
>...</button>
CodePudding user response:
As others have mentioned, this is due to the value being { start: null, end: null }
. You could fix this by creating a custom validator - the benefit of doing it this way is your valid state of your form will be correct.
You could define a validator as a directive as follows (there may be an interface already existing in your date picker package, so may not need that part):
interface DateRange {
start: Moment | null;
end: Moment | null;
}
@Directive({
selector: '[appDateRange]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: DateRangeValidatorDirective,
multi: true,
},
],
})
export class DateRangeValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors | null {
return this.dateRangeValidator(control);
}
dateRangeValidator: ValidatorFn = (
control: AbstractControl
): ValidationErrors | null => {
if (!control.value) return null;
const dateRange = control.value as DateRange;
console.log('VALIDATE', dateRange);
return dateRange.start && dateRange.end ? null : { dateRange: true };
};
}
Make sure to define this in your module also:
@NgModule({
declarations: [
...
DateRangeValidatorDirective
]
...
})
You can then use this, exactly like your required
validator on the input using the directive selector (appDateRange
):
<input ... appDateRange>
So could on your button have:
<button ... [disabled]="date.errors?.required && date.errors?.dateRange"> ...
If you want to find out more about this, there is a very good example here https://angular.io/guide/form-validation, forbiddenNameValidator on the page.