I'm using angular 10 with nebular 6.
What I want to achieve:
I have a form where are two input date fields, start of project
and end of project
. Whether the user wants to enter an invalid date (with nb-datepicker), let's say start of project
is after end of project
the form have to forbid it and immediately set the changed field value back to the previous.
What I already tried with no luck:
(ngModelChange)="validateDate($event)"
before [(ngModel)]="startOfProject"
. It created unpredictable behavior.[(ngModel)]
alltogether and added (change)="validateDate($event)
and kept the old value. Later I found out that this is a bad coding practice and not maintainable.In AngularJS there was $scope.$watch
where one can easily obtain the previous value. What is the Angular 10 way of doing this?
Which datapicker you are using doesn't make any difference, since the functionality you are searching for is based on RxJs and angular ReactiveFormsModule
. You can use formGroup.valueChanges
with RxJs pairwise
<form [formGroup]="dateForm">
<mat-form-field style="margin-right: 10px;">
<input matInput [matDatepicker]="picker" formControlName="startdate" placeholder="Start date"/>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<mat-form-field>
<input matInput [matDatepicker]="picker2" formControlName="enddate" placeholder="End date"/>
<mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
<mat-datepicker #picker2></mat-datepicker>
</mat-form-field>
</form>
dateForm: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.dateForm = this.formBuilder.group({
startdate: [null, Validators.required],
enddate: [null, Validators.required],
});
}
ngOnInit(): void {
this.dateForm.valueChanges.pipe(
startWith({ oldValue: null, newValue: null }),
distinctUntilChanged(),
pairwise(),
map(([oldValue, newValue]) => { return { oldValue, newValue } })
)
.subscribe({
next: (val) => {
console.log(val)
// implement condition and set controls accordingly using
// this.dateForm.controls.startdate.setValue(whatever date)
// this.dateForm.controls.enddate.setValue(whatever date)
}
});
}
Have in mind that this is just basic example explaining how you can do that, but its not complete, to begin with you should add some types here. To formControls
, to rxjs
. You should destroy subscription when no longer needed, etc...
Additionally, I just took whatever project and implemented staff, although this particular example will be practically identical in the latest versions of angular, stackblitz example uses old version of angular, so this is not moduleless, you will be able to optimize some staff if you use angular 16-17