Skip to content

Commit

Permalink
fix(datepicker): start from date typed in input (#1300)
Browse files Browse the repository at this point in the history
  • Loading branch information
yggg committed Mar 14, 2019
1 parent 2a1f113 commit dfc75f0
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { NbCalendarCell, NbCalendarSize } from '../../model';
import { NbCalendarMonthCellComponent } from './calendar-month-cell.component';
import { NbDateService } from '../../services';

export const MONTHS_IN_VIEW = 12;
export const MONTHS_IN_COLUMN = 4;

@Component({
selector: 'nb-calendar-month-picker',
Expand Down Expand Up @@ -73,8 +75,8 @@ export class NbCalendarMonthPickerComponent<D, T> implements OnInit {
}

initMonths() {
const months: D[] = range(12).map(i => this.createMonthDateByIndex(i));
this.months = batch(months, 4);
const months: D[] = range(MONTHS_IN_VIEW).map(i => this.createMonthDateByIndex(i));
this.months = batch(months, MONTHS_IN_COLUMN);
}

onSelect(month: D) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import { NbCalendarCell, NbCalendarSize } from '../../model';
import { NbCalendarYearCellComponent } from './calendar-year-cell.component';
import { NbDateService } from '../../services';


const defaultYearCount = 20;
export const YEARS_IN_VIEW = 20;
export const YEARS_IN_COLUMN = 4;

@Component({
selector: 'nb-calendar-year-picker',
Expand Down Expand Up @@ -83,9 +83,9 @@ export class NbCalendarYearPickerComponent<D> implements OnChanges {

initYears() {
const selectedYear = this.dateService.getYear(this.year);
const startYear = Math.ceil(selectedYear - defaultYearCount / 2);
const years = range(defaultYearCount).map(i => this.createYearDateByIndex(i + startYear));
this.years = batch(years, 4);
const startYear = Math.ceil(selectedYear - YEARS_IN_VIEW / 2);
const years = range(YEARS_IN_VIEW).map(i => this.createYearDateByIndex(i + startYear));
this.years = batch(years, YEARS_IN_COLUMN);
}

onSelect(year) {
Expand Down
12 changes: 10 additions & 2 deletions src/framework/theme/components/calendar-kit/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@

export { NbCalendarHeaderComponent } from './calendar-header/calendar-header.component';
export { NbCalendarDayCellComponent } from './calendar-day-picker/calendar-day-cell.component';
export { NbCalendarYearPickerComponent } from './calendar-year-picker/calendar-year-picker.component';
export { NbCalendarMonthPickerComponent } from './calendar-month-picker/calendar-month-picker.component';
export {
NbCalendarYearPickerComponent,
YEARS_IN_VIEW,
YEARS_IN_COLUMN,
} from './calendar-year-picker/calendar-year-picker.component';
export {
NbCalendarMonthPickerComponent,
MONTHS_IN_VIEW,
MONTHS_IN_COLUMN,
} from './calendar-month-picker/calendar-month-picker.component';
export { NbCalendarDayPickerComponent } from './calendar-day-picker/calendar-day-picker.component';
export { NbCalendarNavigationComponent } from './calendar-navigation/calendar-navigation.component';
export { NbCalendarPageableNavigationComponent } from './calendar-navigation/calendar-pageable-navigation.component';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

import { Component, EventEmitter, HostBinding, Input, OnInit, Output, Type } from '@angular/core';

import { NbDateService, NbCalendarCell, NbCalendarSize, NbCalendarViewMode } from '../calendar-kit';

import { NbDateService, NbCalendarCell, NbCalendarSize, NbCalendarViewMode, YEARS_IN_VIEW } from '../calendar-kit';

/**
* The basis for calendar and range calendar components.
Expand Down Expand Up @@ -139,6 +138,6 @@ export class NbBaseCalendarComponent<D, T> implements OnInit {
}

private changeVisibleYear(direction: number) {
this.visibleDate = this.dateService.addYear(this.visibleDate, direction * 20);
this.visibleDate = this.dateService.addYear(this.visibleDate, direction * YEARS_IN_VIEW);
}
}
17 changes: 14 additions & 3 deletions src/framework/theme/components/datepicker/datepicker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ export class NbDatepickerComponent<D> extends NbBasePicker<D, D, NbCalendarCompo
}

if (date) {
this.visibleDate = date;
this.picker.visibleDate = date;
this.picker.date = date;
}
Expand All @@ -409,7 +410,11 @@ export class NbDatepickerComponent<D> extends NbBasePicker<D, D, NbCalendarCompo
}

protected writeQueue() {
this.value = this.queue;
if (this.queue) {
const date = this.queue;
this.queue = null;
this.value = date;
}
}
}

Expand Down Expand Up @@ -449,7 +454,9 @@ export class NbRangepickerComponent<D> extends NbBasePicker<D, NbCalendarRange<D
}

if (range) {
this.picker.visibleDate = range && range.start;
const visibleDate = range && range.start;
this.visibleDate = visibleDate;
this.picker.visibleDate = visibleDate;
this.picker.range = range;
}
}
Expand All @@ -463,6 +470,10 @@ export class NbRangepickerComponent<D> extends NbBasePicker<D, NbCalendarRange<D
}

protected writeQueue() {
this.value = this.queue;
if (this.queue) {
const range = this.queue;
this.queue = null;
this.value = range;
}
}
}
214 changes: 209 additions & 5 deletions src/framework/theme/components/datepicker/datepicker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
import { ApplicationRef, Component, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { NbDatepickerDirective } from '@nebular/theme';
import { skip } from 'rxjs/operators';
import { NbCalendarRange, NbDatepickerDirective } from '@nebular/theme';

import { NbDatepickerModule } from './datepicker.module';
import { NbThemeModule } from '../../theme.module';
import { NbLayoutModule } from '../layout/layout.module';
import { NbDatepickerComponent } from './datepicker.component';

import { NbDatepickerComponent, NbRangepickerComponent } from './datepicker.component';

@Component({
selector: 'nb-datepicker-test',
Expand All @@ -31,6 +31,22 @@ export class NbDatepickerTestComponent {
@ViewChild(NbDatepickerDirective) datepickerDirective: NbDatepickerDirective<Date>;
}

@Component({
selector: 'nb-rangepicker-test',
template: `
<nb-layout>
<nb-layout-column>
<input [nbDatepicker]="rangepicker">
<nb-rangepicker #rangepicker></nb-rangepicker>
</nb-layout-column>
</nb-layout>
`,
})
export class NbRangepickerTestComponent {
@ViewChild(NbRangepickerComponent) rangepicker: NbRangepickerComponent<Date>;
@ViewChild(NbDatepickerDirective) datepickerDirective: NbDatepickerDirective<Date>;
}

describe('nb-datepicker', () => {
let fixture: ComponentFixture<NbDatepickerTestComponent>;
let appRef: ApplicationRef;
Expand Down Expand Up @@ -101,8 +117,7 @@ describe('nb-datepicker', () => {
cell.dispatchEvent(new Event('click'));
});

it('should select date typed in to the input', () => {
datepicker.visibleDate = new Date(2018, 8, 17);
it('should start from date typed into the input', () => {
input.value = 'Sep 17, 2018';
input.dispatchEvent(new Event('input'));
showDatepicker();
Expand All @@ -113,6 +128,37 @@ describe('nb-datepicker', () => {
expect(cell.textContent).toContain('17');
});

it('should start from current date if input is empty', () => {
showDatepicker();
appRef.tick();
expect(overlay.querySelector('.day-cell.today')).toBeDefined();
});

it('should start from current date if input value is invalid', () => {
input.value = 'definitely not a date';
input.dispatchEvent(new Event('input'));
showDatepicker();
appRef.tick();
expect(overlay.querySelector('.day-cell.today')).toBeDefined();
});

it('should update visible date if input value changed', () => {
const initialDate = new Date(2000, 0, 1);
datepicker.visibleDate = initialDate;

const date = 17;
const month = 8;
const year = 2018;
input.value = 'Sep 17, 2018';
input.dispatchEvent(new Event('input'));
showDatepicker();
appRef.tick();

expect(datepicker.visibleDate.getDate()).toEqual(date);
expect(datepicker.visibleDate.getMonth()).toEqual(month);
expect(datepicker.visibleDate.getFullYear()).toEqual(year);
});

it('should be valid if empty', () => {
expect(datepickerDirective.validate()).toBe(null);
});
Expand All @@ -125,3 +171,161 @@ describe('nb-datepicker', () => {
expect(datepickerDirective.validate()).not.toBe(null);
});
});

describe('nb-rangepicker', () => {
let fixture: ComponentFixture<NbRangepickerTestComponent>;
let appRef: ApplicationRef;
let rangepicker: NbRangepickerComponent<Date>;
let datepickerDirective: NbDatepickerDirective<Date>;
let overlay: HTMLElement;
let input: HTMLInputElement;

const showRangepicker = () => {
rangepicker.show();
appRef.tick();
};

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([]),
NbThemeModule.forRoot(),
NbLayoutModule,
NbDatepickerModule.forRoot(),
],
declarations: [NbRangepickerTestComponent],
});

fixture = TestBed.createComponent(NbRangepickerTestComponent);
appRef = TestBed.get(ApplicationRef);

fixture.detectChanges();
});

beforeEach(() => {
rangepicker = fixture.componentInstance.rangepicker;
datepickerDirective = fixture.componentInstance.datepickerDirective;
overlay = fixture.nativeElement.querySelector('nb-layout');
input = fixture.nativeElement.querySelector('input');
});

it('should render calendar', () => {
showRangepicker();
const calendar = overlay.querySelector('nb-calendar-range');
expect(calendar).toBeTruthy();
});

it('should not render overlay on load', () => {
const datepickerContainer = overlay.querySelector('nb-datepicker-container');
expect(datepickerContainer).toBeNull();
});

it('should render overlay lazily', () => {
const datepickerContainer = overlay.querySelector('nb-datepicker-container');
expect(datepickerContainer).toBeNull();
showRangepicker();
const calendar = overlay.querySelector('nb-calendar-range');
expect(calendar).toBeTruthy();
});

it('should emit rangeChange when selected start date', (done) => {
rangepicker.visibleDate = new Date(2018, 8, 17);
showRangepicker();

rangepicker.rangeChange.subscribe((range: NbCalendarRange<Date>) => {
expect(range.start.getFullYear()).toEqual(2018);
expect(range.start.getMonth()).toEqual(8);
expect(range.start.getDate()).toEqual(1);
expect(range.end).not.toBeDefined();
done();
});

// click on Sep 1
const startCell = overlay.querySelectorAll('.day-cell')[6];
(startCell as HTMLElement).click();

fixture.detectChanges();
}, 5000);

it('should emit rangeChange when selected start and end dates', (done) => {
rangepicker.visibleDate = new Date(2018, 8, 17);
showRangepicker();

rangepicker.rangeChange
.pipe(skip(1))
.subscribe((range: NbCalendarRange<Date>) => {
expect(range.start.getFullYear()).toEqual(2018);
expect(range.end.getFullYear()).toEqual(2018);
expect(range.start.getMonth()).toEqual(8);
expect(range.end.getMonth()).toEqual(8);
expect(range.start.getDate()).toEqual(1);
expect(range.end.getDate()).toEqual(3);
done();
});

// click on Sep 1
const startCell = overlay.querySelectorAll('.day-cell')[6];
(startCell as HTMLElement).click();
// click on Sep 3
const endCell = overlay.querySelectorAll('.day-cell')[8];
(endCell as HTMLElement).click();

fixture.detectChanges();
}, 5000);

it('should start from date typed into the input', () => {
input.value = 'Sep 17, 2018 - Sep 19, 2018';
input.dispatchEvent(new Event('input'));
showRangepicker();
appRef.tick();

const startCell = overlay.querySelector('.day-cell.in-range.start');
const endCell = overlay.querySelector('.day-cell.in-range.end');

expect(startCell.textContent).toContain('17');
expect(endCell.textContent).toContain('19');
});

it('should start from current date if input is empty', () => {
showRangepicker();
appRef.tick();
expect(overlay.querySelector('.day-cell.today')).toBeDefined();
});

it('should start from current date if input value is invalid', () => {
input.value = 'definitely not a date';
input.dispatchEvent(new Event('input'));
showRangepicker();
appRef.tick();
expect(overlay.querySelector('.day-cell.today')).toBeDefined();
});

it('should set visible date to start date if input value changed', () => {
const initialDate = new Date(2000, 0, 1);
rangepicker.visibleDate = initialDate;

const date = 17;
const month = 8;
const year = 2018;
input.value = 'Sep 17, 2018 - Sep 19, 2018';
input.dispatchEvent(new Event('input'));
appRef.tick();
showRangepicker();

expect(rangepicker.visibleDate.getDate()).toEqual(date);
expect(rangepicker.visibleDate.getMonth()).toEqual(month);
expect(rangepicker.visibleDate.getFullYear()).toEqual(year);
});

it('should be valid if empty', () => {
expect(datepickerDirective.validate()).toBe(null);
});

it('should not be valid if empty contain incorrectly formatted date', () => {
input.value = 'somecurruptedinput';
input.dispatchEvent(new Event('input'));
showRangepicker();

expect(datepickerDirective.validate()).not.toBe(null);
});
});

0 comments on commit dfc75f0

Please sign in to comment.