nebular
nebular copied to clipboard
nb-rangepicker - validation - min/max - ngModel - issue
Issue type
I'm submitting a ... (check one with "x")
- [x] bug report
- [ ] feature request
Issue description
Current behavior: ERROR Error: Uncaught (in promise): TypeError: date2.getTime is not a function TypeError: date2.getTime is not a function at NbNativeDateService.push../node_modules/@nebular/theme/components/calendar-kit/services/native-date.service.js.NbNativeDateService.compareDates (native-date.service.js:108)
Expected behavior: Nebular 3 - components - form - datepicker -rangepicker to work with [min] and [max] being set.
Both range and date pickers support all parameters as calendar, so, check NbCalendarComponent for additional info.
Steps to reproduce: https://stackblitz.com/edit/nebular-1281-kmwnav?file=src/app/app.component.ts Using the Validation template replace 'nb-datepicker' to 'nb-rangepicker' and using [(ngModel)]
Related code:
/*
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
import { Component } from '@angular/core';
import { NbDateService } from '@nebular/theme';
@Component({
selector: 'nb-datepicker-validation',
template: `
<div>
<input nbInput placeholder="Form Picker" [nbDatepicker]="picker" [(ngModel)]="ngModelDate">
<nb-rangepicker #picker [min]="min" [max]="max"></nb-rangepicker>
</div>
`,
styles: [`
:host {
display: flex;
justify-content: center;
align-content: center;
height: 40rem;
}
:host input {
width: 21.875rem;
}
`],
})
export class DatepickerValidationComponent {
min: Date;
max: Date;
ngModelDate = {
start: new Date(),
end: new Date(),
};
constructor(protected dateService: NbDateService<Date>) {
this.min = this.dateService.addMonth(this.dateService.today(), -1);
this.max = this.dateService.addMonth(this.dateService.today(), 1);
}
}
Other information:
npm, node, OS, Browser
Node v11.6.0, npm 6.9.0
OS: macOS (Mojave)
Browser: Chrome
Angular, Nebular
"@angular/animations": "^7.2.8",
"@angular/cdk": "^7.3.3",
"@angular/common": "^7.2.8",
"@angular/compiler": "^7.2.8",
"@angular/core": "^7.2.8",
"@angular/forms": "^7.2.8",
"@angular/material": "^7.3.3",
"@angular/platform-browser": "^7.2.8",
"@angular/platform-browser-dynamic": "^7.2.8",
"@angular/router": "^7.2.8",
"@nebular/theme": "^3.4.2",
"angular2-chartjs": "^0.5.1",
"chart.js": "^2.7.3",
"core-js": "^2.6.3",
"hammerjs": "^2.0.8",
"nebular-icons": "^1.1.0",
"ng2-completer": "^2.0.8",
"ng2-smart-table": "^1.3.5",
"ngx-markdown": "^8.0.2",
"rxjs": "~6.4.0",
"rxjs-compat": "^6.4.0",
"tslib": "^1.9.0",
"zone.js": "^0.8.29"
In the meantime, I have created a work around to solve the above problem(s):
<input nbInput placeholder="{{ngModelDate.start | date}} - {{ngModelDate.end | date}}" [nbDatepicker]="ngmodel">
<nb-rangepicker #ngmodel [min]="min" [max]="max"> </nb-rangepicker>
When this bug will be fixed?
managed to workaround it by overriding the comparison method to suit the formControl with the rangePickerDirective in the following manner.
constructor(...) {
this.dateRangesCtrl.patchValue(this.reportsQuery.getValue().dateRange);
let isStart = true;
this.dateService.compareDates = (date1: Date, date2: unknown) => {
let inputVal: Date;
if (isStart) {
inputVal = (date2 as { start: Date; end: Date }).start;
isStart = false;
} else {
inputVal = (date2 as { start: Date; end: Date }).end;
isStart = true;
}
return date1 === inputVal ? 0 : date1 > inputVal ? 1 : -1;
};
this.min = this.dateService.createDate(2019, 1, 1);
this.max = new Date();
}
and in template
<input nbInput placeholder="Pick Date Range" class="date-picker" [nbDatepicker]="formpicker" [formControl]="dateRangesCtrl" />
<nb-rangepicker #formpicker [min]="min" [max]="max"></nb-rangepicker>
@DanielNetzeriAm use formcontrol & (min、max) together will throw error "date.clone is not function"
@zhanghongyublog I set defult value use [value] in input template. give up use formControl or ngModel
<input nbInput [nbDatepicker]="formpicker" [value]="fakeInputValue">
<nb-rangepicker #formpicker [min]="min" [max]="max"></nb-rangepicker>
value is pure string can avoid throw error "date.clone is not function" or "date2.getTime is not a function"
this.fakeInputValue = ${dayjs(new Date()).format('YYYY/MM/DD')} - ${dayjs(new Date()).format('YYYY/MM/DD')}`;
@zhanghongyublog I have the same problem. FormControl With min and max throw the error "date.clone is not function"
@DanielNetzeriAm great workaround, thanks!
I think it could be the only possible workaround for the rangepicker for now, because the compare function of NbNativeDateService does:

supposing that date1 and date2 are of type Date, which is okay for the datepicker. But the values of the rangepicker are more complex and represented as an object {start: Date, end: Date}, so {start: Date, end: Date}.getTime() in the compare function does not make any sense and causes the problem.
But I am sure, you know that already :) Just leaving the comment to save the debugging time for someone, who may run into the same problem.
Thanks a lot for your solution!
Bug is still here. 3 years later.
my quickest solution at the moment is import NbDateFnsDateModule into your component/module
and then
export class MyComponent implements Oninit {
minDate: Date = addDays(new Date(), -1);
maxDate: Date = addDays(new Date(), 365);
private dateService = inject(NbDateService);
//or if you still using constructor for DI, then put this in constructor(private dateService...)
...
constructor(...) {
this.dateService.compareDates = (date1: Date, date2: { start: Date; end: Date }, isStartDate = true) =>
Math.sign(date1.getTime() - (isStartDate ? date2.start : date2.end).getTime());
}
}
<nb-form-field>
<input nbInput fullWidth [nbDatepicker]="effectiveDateRange" formControlName="effectiveDateRange"
id="effectiveDateRange">
<nb-rangepicker [min]="minDate" [max]="maxDate" format="MMM dd yyyy" #effectiveDateRange></nb-rangepicker>
</nb-form-field>
just make sure you have date-fns and @nebular/date-fns