Skip to content
This repository has been archived by the owner on Mar 27, 2023. It is now read-only.

Commit

Permalink
[NG] Date Picker Output Bug Fix
Browse files Browse the repository at this point in the history
Signed-off-by: Aditya Bhandari <adityab@vmware.com>
  • Loading branch information
Aditya Bhandari authored and adibwoy committed Jun 6, 2018
1 parent 600aace commit 9a729b9
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 25 deletions.
101 changes: 96 additions & 5 deletions src/clr-angular/forms/datepicker/date-input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ export default function() {

expect(dateNavigationService.selectedDay).toBeNull();
});

it('outputs the date when the user selects a Date from the Date Picker', () => {
expect(context.testComponent.date).toBeUndefined();

dateNavigationService.notifySelectedDayChanged(new DayModel(2015, 1, 1));

expect(context.testComponent.date.getFullYear()).toBe(2015);
expect(context.testComponent.date.getMonth()).toBe(1);
expect(context.testComponent.date.getDate()).toBe(1);
});

it('outputs the date when the user changes the date manually in th input', () => {
expect(context.testComponent.date).toBeUndefined();

const input: HTMLInputElement = context.testElement.querySelector('input');
input.value = '01/01/2015';
input.dispatchEvent(new Event('change'));

expect(context.testComponent.date.getFullYear()).toBe(2015);
expect(context.testComponent.date.getMonth()).toBe(0);
expect(context.testComponent.date.getDate()).toBe(1);

input.value = '01/01/201';
input.dispatchEvent(new Event('change'));

expect(context.testComponent.date).toBe(null);
});
});

describe('Date Display', () => {
Expand Down Expand Up @@ -250,6 +277,30 @@ export default function() {
expect(dateNavigationService.selectedDay.date).toBe(5);
});

it('outputs the date when the user manually changes the date', () => {
const inputEl: HTMLInputElement = fixture.nativeElement.querySelector('input');
let date: Date = fixture.componentInstance.dateOutput;

expect(date).toBeUndefined();
inputEl.value = '01/01/2012';
inputEl.dispatchEvent(new Event('change'));
fixture.detectChanges();

date = fixture.componentInstance.dateOutput;

expect(date.getFullYear()).toBe(2012);
expect(date.getMonth()).toBe(0);
expect(date.getDate()).toBe(1);

inputEl.value = '01/01/201';
inputEl.dispatchEvent(new Event('change'));
fixture.detectChanges();

date = fixture.componentInstance.dateOutput;

expect(date).toBeNull();
});

it('marks the form as touched when the markAsTouched event is received', () => {
const date = fixture.componentInstance.testForm.get('date');
expect(date.touched).toBe(false);
Expand Down Expand Up @@ -310,6 +361,30 @@ export default function() {
done();
});
});

it('outputs the date when the user manually changes the date', () => {
const inputEl: HTMLInputElement = fixture.nativeElement.querySelector('input');
let date: Date = fixture.componentInstance.dateOutput;

expect(date).toBeUndefined();
inputEl.value = '01/01/2012';
inputEl.dispatchEvent(new Event('change'));
fixture.detectChanges();

date = fixture.componentInstance.dateOutput;

expect(date.getFullYear()).toBe(2012);
expect(date.getMonth()).toBe(0);
expect(date.getDate()).toBe(1);

inputEl.value = '01/01/201';
inputEl.dispatchEvent(new Event('change'));
fixture.detectChanges();

date = fixture.componentInstance.dateOutput;

expect(date).toBeNull();
});
});

describe('Datepicker with clrDate', () => {
Expand Down Expand Up @@ -389,10 +464,16 @@ export default function() {

@Component({
template: `
<input type="date" clrDate>
<input type="date" clrDate (clrDateChange)="dateChanged($event)">
`,
})
class TestComponent {}
class TestComponent {
date: Date;

dateChanged(date: Date) {
this.date = date;
}
}

@Component({
template: `
Expand All @@ -417,24 +498,34 @@ class TestComponentWithClrDate {
@Component({
template: `
<form [formGroup]="testForm">
<input id="dateControl" type="date" clrDate formControlName="date">
<input id="dateControl" type="date" clrDate (clrDateChange)="dateChanged($event)" formControlName="date">
</form>
`,
})
class TestComponentWithReactiveForms {
dateInput: string = '01/01/2015';
testForm = new FormGroup({ date: new FormControl(this.dateInput) });

dateOutput: Date;

dateChanged(date: Date) {
this.dateOutput = date;
}
}

@Component({
template: `
<form #templateForm="ngForm">
<input type="date" clrDate [(ngModel)]="dateInput" name="date">
<input type="date" clrDate (clrDateChange)="dateChanged($event)" [(ngModel)]="dateInput" name="date">
</form>
{{templateForm.touched}}
`,
})
class TestComponentWithTemplateDrivenForms {
@ViewChild('templateForm') templateForm: NgForm;
dateInput: string = '01/01/2015';
dateOutput: Date;

dateChanged(date: Date) {
this.dateOutput = date;
}
}
58 changes: 39 additions & 19 deletions src/clr-angular/forms/datepicker/date-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement
*/
private _subscriptions: Subscription[] = [];

//We need this variable because if the date input has a value initialized
//we do not output it. This variable is false during initial load. We make sure that
//during initial load dayModelOutputted is equal to the value entered by the user so that initialized
//value isn't emitted back to the user. After initial load,
//we set this to true and the dayModelOutputted is set only
//when the Output is emitted to the user.
private previousOutputInitializedFlag: boolean = false;
private previousOutput: DayModel;

private initializePreviousOutput(dayModel: DayModel) {
if (!this.previousOutputInitializedFlag) {
this.previousOutput = dayModel;
this.previousOutputInitializedFlag = true;
}
}

constructor(
@Optional() private container: ClrDateContainer,
vcr: ViewContainerRef,
Expand Down Expand Up @@ -86,6 +102,7 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement
// Will explore that later and see if its a cleaner solution.
if (this._ngControl && this._ngControl.value) {
this.updateInputValue(this._ngControl.value);
this.initializePreviousOutput(this._dateNavigationService.selectedDay);
}
}

Expand Down Expand Up @@ -209,6 +226,16 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement

@Output('clrDateChange') _dateUpdated: EventEmitter<Date> = new EventEmitter<Date>(false);

private emitDateOutput(dayModel: DayModel): void {
if (dayModel && !dayModel.isEqual(this.previousOutput)) {
this._dateUpdated.emit(dayModel.toDate());
this.previousOutput = dayModel;
} else if (!dayModel && this.previousOutput) {
this._dateUpdated.emit(null);
this.previousOutput = null;
}
}

/**
* Fires this method when the user changes the input focuses out of the input field.
*/
Expand All @@ -218,15 +245,11 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement
const date: Date = this._dateIOService.isValidInput(value);
if (date) {
const dayModel: DayModel = new DayModel(date.getFullYear(), date.getMonth(), date.getDate());
if (!dayModel.isEqual(this._dateNavigationService.selectedDay)) {
this._dateNavigationService.selectedDay = dayModel;
this._dateUpdated.emit(date);
}
this._dateNavigationService.selectedDay = dayModel;
this.emitDateOutput(dayModel);
} else {
if (this._dateNavigationService.selectedDay) {
this._dateNavigationService.selectedDay = null;
this._dateUpdated.emit(null);
}
this._dateNavigationService.selectedDay = null;
this.emitDateOutput(null);
}
}

Expand All @@ -238,7 +261,6 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement
// This subscription is fired when the user selects a date from the popover.
this._subscriptions.push(
this._dateNavigationService.selectedDayChange.subscribe((dayModel: DayModel) => {
const date: Date = dayModel.toDate();
const dateStr: string = this._dateIOService.toLocaleDisplayFormatString(dayModel.toDate());
this.writeDateStrToInputField(dateStr);
// This makes sure that ngModelChange is fired
Expand All @@ -248,7 +270,7 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement
if (this._ngControl) {
this._ngControl.control.setValue(dateStr);
}
this._dateUpdated.emit(date);
this.emitDateOutput(dayModel);
})
);

Expand All @@ -257,15 +279,13 @@ export class ClrDateInput extends WrappedFormControl<ClrDateContainer> implement
if (this._ngControl) {
this._subscriptions.push(
this._ngControl.valueChanges.subscribe((value: string) => {
if (value) {
const date: Date = this._dateIOService.isValidInput(value);
if (date) {
this._dateNavigationService.selectedDay = new DayModel(
date.getFullYear(),
date.getMonth(),
date.getDate()
);
}
const date: Date = this._dateIOService.isValidInput(value);
if (date) {
const dayModel: DayModel = new DayModel(date.getFullYear(), date.getMonth(), date.getDate());
this._dateNavigationService.selectedDay = dayModel;
this.initializePreviousOutput(dayModel);
} else {
this.initializePreviousOutput(null);
}
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export class DateNavigationService {
return this._selectedDayChange.asObservable();
}

/**
* Notifies that the selected day has changed so that the date can be emitted to the user.
* Note: Only to be called from day.ts
*/
notifySelectedDayChanged(dayModel: DayModel) {
if (dayModel.isEqual(this.selectedDay)) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h3>Simple Reactive Form</h3>
<section class="form-block">
<div class="form-group">
<label for="dateControl">Date</label>
<input id="dateControl" type="date" clrDate formControlName="date"/>
<input id="dateControl" type="date" clrDate (clrDateChange)="dateChanged($event)" formControlName="date"/>
</div>
<div class="form-group">
<label for="nameControl">Name</label>
Expand Down
4 changes: 4 additions & 0 deletions src/dev/src/app/datepicker/datepicker-in-reactive-forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ import { FormControl, FormGroup } from '@angular/forms';
})
export class DatepickerInReactiveForms {
dateForm = new FormGroup({ date: new FormControl('03/05/2018'), name: new FormControl('Jane') });

dateChanged(date: Date) {
console.log(date);
}
}

0 comments on commit 9a729b9

Please sign in to comment.