akveo / nebular

:boom: Customizable Angular UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/nebular
MIT License
8.04k stars 1.51k forks source link

nb-rangepicker - validation - min/max - ngModel - issue #1651

Open chrischak opened 5 years ago

chrischak commented 5 years ago

Issue type

I'm submitting a ... (check one with "x")

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"
chrischak commented 4 years ago

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>
prernagp commented 4 years ago

When this bug will be fixed?

DanielNetzeriAm commented 4 years ago

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>
april-zhy commented 4 years ago

@DanielNetzeriAm use formcontrol & (min、max) together will throw error "date.clone is not function"

wan-zhen commented 4 years ago

@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')}`;
LuisUrrutia commented 4 years ago

@zhanghongyublog I have the same problem. FormControl With min and max throw the error "date.clone is not function"

bohdandakhno commented 3 years ago

@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:

image

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!

poletaew commented 2 years ago

Bug is still here. 3 years later.