Skip to content

Commit fe68b6f

Browse files
fix(date-range-picker): set internal value of picker with present ngModels #7353
refactor(date-editor): expose ngControl
1 parent 87dee68 commit fe68b6f

File tree

5 files changed

+70
-20
lines changed

5 files changed

+70
-20
lines changed

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ export class IgxDateRangeInputsBaseComponent extends IgxInputGroupComponent {
7777
public updateInputValidity(state: IgxInputState) {
7878
this.inputDirective.valid = state;
7979
}
80-
8180
}
8281

8382
/**

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.spec.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,8 @@ describe('IgxDateRangePicker', () => {
491491
TestBed.configureTestingModule({
492492
declarations: [
493493
DateRangeTestComponent,
494-
DateRangeTwoInputsTestComponent
494+
DateRangeTwoInputsTestComponent,
495+
DateRangeTwoInputsNgModelTestComponent
495496
],
496497
imports: [IgxDateRangePickerModule, IgxDateTimeEditorModule, IgxInputGroupModule, FormsModule, NoopAnimationsModule]
497498
})
@@ -584,6 +585,7 @@ describe('IgxDateRangePicker', () => {
584585
verifyDateRange();
585586
});
586587
});
588+
587589
describe('Keyboard navigation', () => {
588590
it('should toggle the calendar with ALT + DOWN/UP ARROW key', fakeAsync(() => {
589591
expect(dateRange.collapsed).toBeTruthy();
@@ -630,6 +632,19 @@ describe('IgxDateRangePicker', () => {
630632
expect(dateRange.onClosed.emit).toHaveBeenCalledTimes(1);
631633
}));
632634
});
635+
636+
describe('Data binding', () => {
637+
it('should properly update component value with ngModel bound to projected inputs - #7353', fakeAsync(() => {
638+
fixture = TestBed.createComponent(DateRangeTwoInputsNgModelTestComponent);
639+
fixture.detectChanges();
640+
const range = { start: new Date(2020, 1, 1), end: new Date(2020, 1, 4) };
641+
fixture.componentInstance.dateRange.open();
642+
fixture.detectChanges();
643+
tick();
644+
expect(fixture.componentInstance.dateRange.value.start.getTime()).toEqual(range.start.getTime());
645+
expect(fixture.componentInstance.dateRange.value.end.getTime()).toEqual(range.end.getTime());
646+
}));
647+
});
633648
});
634649

635650
describe('Calendar UI', () => {
@@ -821,6 +836,22 @@ export class DateRangeTwoInputsTestComponent extends DateRangeTestComponent {
821836
range;
822837
}
823838

839+
@Component({
840+
selector: 'igx-date-range-two-inputs-ng-model',
841+
template: `
842+
<igx-date-range-picker [mode]="'dropdown'">
843+
<igx-date-range-start>
844+
<input igxInput [(ngModel)]="range.start" igxDateTimeEditor>
845+
</igx-date-range-start>
846+
<igx-date-range-end>
847+
<input igxInput [(ngModel)]="range.end" igxDateTimeEditor>
848+
</igx-date-range-end>
849+
</igx-date-range-picker>`
850+
})
851+
export class DateRangeTwoInputsNgModelTestComponent extends DateRangeTestComponent {
852+
public range = { start: new Date(2020, 1, 1), end: new Date(2020, 1, 4) };
853+
}
854+
824855
@Component({
825856
selector: 'igx-date-range-single-input-label-test',
826857
template: `

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ import {
5252
IgxPickerToggleComponent
5353
} from './date-range-picker-inputs.common';
5454

55-
56-
5755
/**
5856
* Provides the ability to select a range of dates from a calendar UI or editable inputs.
5957
*
@@ -638,8 +636,12 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
638636
if (this._ngControl) {
639637
this._statusChanges$ = this._ngControl.statusChanges.subscribe(this.onStatusChanged.bind(this));
640638
}
641-
this.initialSetValue();
642-
this.updateInputs();
639+
640+
// delay the invocation of initialSetValue
641+
// until the current change detection cycle has completed
642+
Promise.resolve().then(() => {
643+
this.initialSetValue();
644+
});
643645
}
644646

645647
/** @hidden @internal */
@@ -915,13 +917,23 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
915917
}
916918

917919
private initialSetValue() {
918-
// if there is no value, no ngControl but we have inputs we may have value set trough
919-
// inputs' ngModels - we should generate our initial control value
920-
if (!this.value && this.hasProjectedInputs && !this._ngControl) {
921-
const start = this.projectedInputs.find(i => i instanceof IgxDateRangeStartComponent).dateTimeEditor.value;
922-
const end = this.projectedInputs.find(i => i instanceof IgxDateRangeEndComponent).dateTimeEditor.value;
923-
this.updateValue({ start, end });
924-
920+
// if there is no value and no ngControl on the picker but we have inputs we may have value set through
921+
// their ngModels - we should generate our initial control value
922+
if ((!this.value || (!this.value.start && !this.value.end)) && this.hasProjectedInputs && !this._ngControl) {
923+
const start = this.projectedInputs.find(i => i instanceof IgxDateRangeStartComponent);
924+
const end = this.projectedInputs.find(i => i instanceof IgxDateRangeEndComponent);
925+
const value = {
926+
start: start.dateTimeEditor.value,
927+
end: end.dateTimeEditor.value
928+
};
929+
930+
if (start.dateTimeEditor.ngControl && end.dateTimeEditor.ngControl) {
931+
// ngModel will handle value setting in the editors
932+
// we need to only set the internal value of the picker
933+
this._value = value;
934+
} else {
935+
this.updateValue(value);
936+
}
925937
}
926938
}
927939

projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ describe('IgxDateTimeEditor', () => {
2626
let inputFormat: string;
2727
let inputDate: string;
2828
function initializeDateTimeEditor(control?: NgControl) {
29-
// const injector = { get: () => control };
30-
dateTimeEditor = new IgxDateTimeEditorDirective(renderer2, elementRef, maskParsingService, DOCUMENT, locale);
29+
const injector = { get: () => control };
30+
dateTimeEditor = new IgxDateTimeEditorDirective(renderer2, elementRef, maskParsingService, DOCUMENT, locale, injector);
3131
dateTimeEditor.inputFormat = inputFormat;
3232
dateTimeEditor.ngOnInit();
3333

projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
Directive, Input, ElementRef,
3-
Renderer2, NgModule, Output, EventEmitter, Inject, LOCALE_ID, OnChanges, SimpleChanges, Host, Optional, Injector
3+
Renderer2, NgModule, Output, EventEmitter, Inject, LOCALE_ID, OnChanges, SimpleChanges, Host, Optional, Injector, OnInit
44
} from '@angular/core';
55
import {
66
ControlValueAccessor,
@@ -51,7 +51,7 @@ import { IgxDateTimeEditorEventArgs, DatePartInfo, DatePart } from './date-time-
5151
{ provide: NG_VALIDATORS, useExisting: IgxDateTimeEditorDirective, multi: true }
5252
]
5353
})
54-
export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnChanges, Validator, ControlValueAccessor {
54+
export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnChanges, OnInit, Validator, ControlValueAccessor {
5555
/**
5656
* Locale settings used for value formatting.
5757
*
@@ -188,6 +188,9 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
188188
@Output()
189189
public validationFailed = new EventEmitter<IgxDateTimeEditorEventArgs>();
190190

191+
/** @hidden @internal */
192+
public ngControl: NgControl;
193+
191194
private _value: Date;
192195
private _format: string;
193196
private document: Document;
@@ -236,7 +239,8 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
236239
protected elementRef: ElementRef,
237240
protected maskParser: MaskParsingService,
238241
@Inject(DOCUMENT) private _document: any,
239-
@Inject(LOCALE_ID) private _locale: any) {
242+
@Inject(LOCALE_ID) private _locale: any,
243+
private injector: Injector) {
240244
super(elementRef, maskParser, renderer);
241245
this.document = this._document as Document;
242246
this.locale = this.locale || this._locale;
@@ -256,6 +260,10 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
256260
}
257261
}
258262

263+
public ngOnInit(): void {
264+
this.ngControl = this.injector.get<NgControl>(NgControl, null);
265+
}
266+
259267
/** Clear the input element value. */
260268
public clear(): void {
261269
this.updateValue(null);
@@ -569,8 +577,8 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
569577
return date && date.getTime && !isNaN(date.getTime());
570578
}
571579

572-
// TODO: move parseDate to utils
573-
public parseDate(val: string): Date | null {
580+
// TODO: move parseDate to utils
581+
public parseDate(val: string): Date | null {
574582
if (!val) { return null; }
575583
return DatePickerUtil.parseValueFromMask(val, this._inputDateParts, this.promptChar);
576584
}

0 commit comments

Comments
 (0)