Skip to content

Commit

Permalink
fix(datepicker): support NgbDateAdapter in NgbInputDatepicker
Browse files Browse the repository at this point in the history
Fixes #2002

Closes #2003
  • Loading branch information
maxokorokov authored and pkozlowski-opensource committed Dec 15, 2017
1 parent 513f2ff commit 0e325ca
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
28 changes: 18 additions & 10 deletions src/datepicker/datepicker-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {NgbDateParserFormatter} from './ngb-date-parser-formatter';

import {positionElements, PlacementArray} from '../util/positioning';
import {NgbDateStruct} from './ngb-date-struct';
import {NgbDateAdapter} from './ngb-date-adapter';
import {NgbCalendar} from './ngb-calendar';
import {NgbDatepickerService} from './datepicker-service';

Expand Down Expand Up @@ -163,7 +164,8 @@ export class NgbInputDatepicker implements OnChanges,
constructor(
private _parserFormatter: NgbDateParserFormatter, private _elRef: ElementRef, private _vcRef: ViewContainerRef,
private _renderer: Renderer2, private _cfr: ComponentFactoryResolver, ngZone: NgZone,
private _service: NgbDatepickerService, private _calendar: NgbCalendar) {
private _service: NgbDatepickerService, private _calendar: NgbCalendar,
private _ngbDateAdapter: NgbDateAdapter<any>) {
this._zoneSubscription = ngZone.onStable.subscribe(() => {
if (this._cRef) {
positionElements(
Expand All @@ -187,28 +189,29 @@ export class NgbInputDatepicker implements OnChanges,
return null;
}

if (!this._calendar.isValid(value)) {
const ngbDate = this._fromDateStruct(this._ngbDateAdapter.fromModel(value));

if (!this._calendar.isValid(ngbDate)) {
return {'ngbDate': {invalid: c.value}};
}

if (this.minDate && NgbDate.from(value).before(NgbDate.from(this.minDate))) {
if (this.minDate && ngbDate.before(NgbDate.from(this.minDate))) {
return {'ngbDate': {requiredBefore: this.minDate}};
}

if (this.maxDate && NgbDate.from(value).after(NgbDate.from(this.maxDate))) {
if (this.maxDate && ngbDate.after(NgbDate.from(this.maxDate))) {
return {'ngbDate': {requiredAfter: this.maxDate}};
}
}

writeValue(value) {
const ngbDate = value ? new NgbDate(value.year, value.month, value.day) : null;
this._model = this._calendar.isValid(value) ? ngbDate : null;
this._model = this._fromDateStruct(this._ngbDateAdapter.fromModel(value));
this._writeModelValue(this._model);
}

manualDateChange(value: string, updateView = false) {
this._model = this._service.toValidDate(this._parserFormatter.parse(value), null);
this._onChange(this._model ? this._model.toStruct() : (value === '' ? null : value));
this._model = this._fromDateStruct(this._parserFormatter.parse(value));
this._onChange(this._model ? this._ngbDateAdapter.toModel(this._model) : (value === '' ? null : value));
if (updateView && this._model) {
this._writeModelValue(this._model);
}
Expand All @@ -228,7 +231,7 @@ export class NgbInputDatepicker implements OnChanges,
this._applyDatepickerInputs(this._cRef.instance);
this._subscribeForDatepickerOutputs(this._cRef.instance);
this._cRef.instance.ngOnInit();
this._cRef.instance.writeValue(this._model);
this._cRef.instance.writeValue(this._ngbDateAdapter.toModel(this._model));

// date selection event handling
this._cRef.instance.registerOnChange((selectedDate) => {
Expand Down Expand Up @@ -318,8 +321,13 @@ export class NgbInputDatepicker implements OnChanges,
private _writeModelValue(model: NgbDate) {
this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format(model));
if (this.isOpen()) {
this._cRef.instance.writeValue(model);
this._cRef.instance.writeValue(this._ngbDateAdapter.toModel(model));
this._onTouched();
}
}

private _fromDateStruct(date: NgbDateStruct): NgbDate {
const ngbDate = date ? new NgbDate(date.year, date.month, date.day) : null;
return this._calendar.isValid(ngbDate) ? ngbDate : null;
}
}
26 changes: 16 additions & 10 deletions src/datepicker/ngb-date-adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,36 @@ describe('ngb-date model adapter', () => {

describe('fromModel', () => {

it('should convert null undefined as null', () => {
it('should convert invalid and incomplete values to null', () => {
expect(adapter.fromModel(null)).toBeNull();
expect(adapter.fromModel(undefined)).toBeNull();
expect(adapter.fromModel(<any>'')).toBeNull();
expect(adapter.fromModel(<any>'s')).toBeNull();
expect(adapter.fromModel(<any>2)).toBeNull();
expect(adapter.fromModel(<any>{})).toBeNull();
expect(adapter.fromModel(<any>new Date())).toBeNull();
expect(adapter.fromModel(<any>{year: 2017, month: 10})).toBeNull();
});

it('should convert valid date',
() => { expect(adapter.fromModel({year: 2016, month: 5, day: 1})).toEqual({year: 2016, month: 5, day: 1}); });

it('should do its best parsing incomplete dates',
() => { expect(adapter.fromModel({year: 2011, month: 5, day: null})).toEqual({year: 2011, month: 5, day: 1}); });
});

describe('toModel', () => {

it('should convert null and undefined as null', () => {
expect(adapter.toModel(null)).toBe(null);
expect(adapter.toModel(undefined)).toBe(null);
it('should convert invalid and incomplete values to null', () => {
expect(adapter.toModel(null)).toBeNull();
expect(adapter.toModel(undefined)).toBeNull();
expect(adapter.toModel(<any>'')).toBeNull();
expect(adapter.toModel(<any>'s')).toBeNull();
expect(adapter.toModel(<any>2)).toBeNull();
expect(adapter.toModel(<any>{})).toBeNull();
expect(adapter.toModel(<any>new Date())).toBeNull();
expect(adapter.toModel(<any>{year: 2017, month: 10})).toBeNull();
});

it('should convert a valid date',
() => { expect(adapter.toModel({year: 2016, month: 10, day: 15})).toEqual({year: 2016, month: 10, day: 15}); });

it('should try its best with invalid dates',
() => { expect(adapter.toModel({year: 2016, month: 10, day: null})).toEqual({year: 2016, month: 10, day: 1}); });
});

});
4 changes: 2 additions & 2 deletions src/datepicker/ngb-date-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class NgbDateStructAdapter extends NgbDateAdapter<NgbDateStruct> {
* @return {NgbDateStruct}
*/
fromModel(date: NgbDateStruct): NgbDateStruct {
return date ? {year: date.year, month: date.month, day: date.day || 1} : null;
return (date && date.year && date.month && date.day) ? {year: date.year, month: date.month, day: date.day} : null;
}

/**
Expand All @@ -42,6 +42,6 @@ export class NgbDateStructAdapter extends NgbDateAdapter<NgbDateStruct> {
* @return {NgbDateStruct}
*/
toModel(date: NgbDateStruct): NgbDateStruct {
return date ? {year: date.year, month: date.month, day: date.day || 1} : null;
return (date && date.year && date.month && date.day) ? {year: date.year, month: date.month, day: date.day} : null;
}
}

0 comments on commit 0e325ca

Please sign in to comment.