Skip to content

Commit

Permalink
fix(datePicker): Add onValueChanged to handle input changes #5437
Browse files Browse the repository at this point in the history
  • Loading branch information
nrobakova committed Jul 29, 2019
1 parent 1729b79 commit a43a114
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Ignite UI for Angular Change Log

All notable changes for each version of this project will be documented in this file.
## 7.3.12
- `IgxDatePicker` changes
- `onValueChanged` event is added.

## 7.3.7
- **Behavioral Change** default min column width is changed according the grid display density property:
Expand Down
3 changes: 2 additions & 1 deletion projects/igniteui-angular/src/lib/date-picker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ In order to re-template a date picker in `dropdown` mode, an element should be m
```html
<igx-date-picker>
<ng-template igxDatePickerTemplate let-openDialog="openDialog" let-value="value" let-displayData="displayData">
<igx-input-group (click)="openDialog()" #dropDownTarget>
<igx-input-group (click)="openDialog()" #dropDownTarget>
<label igxLabel>Date</label>
<input igxInput [value]="displayData"/>
</igx-input-group>
Expand Down Expand Up @@ -137,6 +137,7 @@ The DatePicker action buttons could be retemplated.
| `onClose` | `datePicker` | Emitted when a datePicker calendar is being closed. |
| `onDisabledDate` | `IDatePickerDisabledDateEventArgs` | Emitted when a disabled date is entered in `dropdown` mode. |
| `onValidationFailed` | `IDatePickerValidationFailedEventArgs` | Emitted when an invalid date is entered in `dropdown` mode. |
| `onValueChanged` | `IDatePickerValueChangedEventArgs` | Fired when date picker value is changed |

### Methods
| Name | Arguments | Return Type | Description |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { async, fakeAsync, TestBed, tick, flush, ComponentFixture } from '@angul
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { IgxDatePickerComponent, IgxDatePickerModule } from './date-picker.component';
import { IgxDatePickerComponent, IgxDatePickerModule, IDatePickerValueChangedEventArgs } from './date-picker.component';
import { IgxLabelDirective } from '../directives/label/label.directive';
import { IgxInputDirective } from '../directives/input/input.directive';
import { UIInteractions, wait } from '../test-utils/ui-interactions.spec';
Expand Down Expand Up @@ -74,15 +74,15 @@ describe('IgxDatePicker', () => {
const dom = fixture.debugElement;
const target = dom.query(By.css('.igx-date-picker__input-date'));

spyOn(datePicker.onOpen, 'emit');
spyOn(datePicker.onClose, 'emit');
spyOn(datePicker.onOpened, 'emit');
spyOn(datePicker.onClosed, 'emit');

UIInteractions.clickElement(target);
fixture.detectChanges();
await wait();

expect(datePicker.onOpen.emit).toHaveBeenCalled();
expect(datePicker.onOpen.emit).toHaveBeenCalledWith(datePicker);
expect(datePicker.onOpened.emit).toHaveBeenCalled();
expect(datePicker.onOpened.emit).toHaveBeenCalledWith(datePicker);

const overlayDiv = document.getElementsByClassName('igx-overlay__wrapper--modal')[0];
expect(overlayDiv).toBeDefined();
Expand All @@ -92,17 +92,24 @@ describe('IgxDatePicker', () => {
fixture.detectChanges();
await wait();

expect(datePicker.onClose.emit).toHaveBeenCalled();
expect(datePicker.onClose.emit).toHaveBeenCalledWith(datePicker);
expect(datePicker.onClosed.emit).toHaveBeenCalled();
expect(datePicker.onClosed.emit).toHaveBeenCalledWith(datePicker);
});

it('Datepicker onSelection event and selectDate method propagation', () => {
it('Datepicker onSelection and onValueChanged events and selectDate method propagation', () => {
spyOn(datePicker.onSelection, 'emit');
spyOn(datePicker.onValueChanged, 'emit');
const newDate: Date = new Date(2016, 4, 6);
const valueChangedArgs: IDatePickerValueChangedEventArgs = {
oldValue: datePicker.value,
newValue: newDate
};
datePicker.selectDate(newDate);
fixture.detectChanges();

expect(datePicker.onSelection.emit).toHaveBeenCalled();
expect(datePicker.onValueChanged.emit).toHaveBeenCalled();
expect(datePicker.onValueChanged.emit).toHaveBeenCalledWith(valueChangedArgs);
expect(datePicker.value).toBe(newDate);
});

Expand Down Expand Up @@ -611,15 +618,15 @@ describe('IgxDatePicker', () => {
const iconDate = dom.query(By.css('.igx-icon'));
expect(iconDate).not.toBeNull();

spyOn(datePicker.onOpen, 'emit');
spyOn(datePicker.onClose, 'emit');
spyOn(datePicker.onOpened, 'emit');
spyOn(datePicker.onClosed, 'emit');

UIInteractions.clickElement(iconDate);
fixture.detectChanges();
await wait();

expect(datePicker.onOpen.emit).toHaveBeenCalled();
expect(datePicker.onOpen.emit).toHaveBeenCalledWith(datePicker);
expect(datePicker.onOpened.emit).toHaveBeenCalled();
expect(datePicker.onOpened.emit).toHaveBeenCalledWith(datePicker);

const dropDown = document.getElementsByClassName('igx-date-picker--dropdown');
expect(dropDown.length).toBe(1);
Expand All @@ -630,8 +637,8 @@ describe('IgxDatePicker', () => {
fixture.detectChanges();
await wait();

expect(datePicker.onClose.emit).toHaveBeenCalled();
expect(datePicker.onClose.emit).toHaveBeenCalledWith(datePicker);
expect(datePicker.onClosed.emit).toHaveBeenCalled();
expect(datePicker.onClosed.emit).toHaveBeenCalledWith(datePicker);
});

it('Handling keyboard navigation with `space`(open) and `esc`(close) buttons - dropdown mode', fakeAsync(() => {
Expand Down Expand Up @@ -677,13 +684,20 @@ describe('IgxDatePicker', () => {
expect(overlays.length).toEqual(0);
}));

it('Datepicker onSelection event and selectDate method propagation - dropdown mode', () => {
it('Datepicker onSelection and onValueChanged events and selectDate method propagation - dropdown mode', () => {
spyOn(datePicker.onSelection, 'emit');
spyOn(datePicker.onValueChanged, 'emit');
const newDate: Date = new Date(2016, 4, 6);
const valueChangedArgs: IDatePickerValueChangedEventArgs = {
oldValue: datePicker.value,
newValue: newDate
};
datePicker.selectDate(newDate);
fixture.detectChanges();

expect(datePicker.onSelection.emit).toHaveBeenCalled();
expect(datePicker.onValueChanged.emit).toHaveBeenCalled();
expect(datePicker.onValueChanged.emit).toHaveBeenCalledWith(valueChangedArgs);
expect(datePicker.value).toBe(newDate);

const input = fixture.debugElement.query(By.directive(IgxInputDirective));
Expand Down Expand Up @@ -923,12 +937,19 @@ describe('IgxDatePicker', () => {
}));

it('should reset value on clear button click - dropdown mode', () => {
spyOn(datePicker.onValueChanged, 'emit');
const valueChangedArgs: IDatePickerValueChangedEventArgs = {
oldValue: datePicker.value,
newValue: null
};
const input = fixture.debugElement.query(By.directive(IgxInputDirective));
const dom = fixture.debugElement;
const clear = dom.queryAll(By.css('.igx-icon'))[1];
UIInteractions.clickElement(clear);
fixture.detectChanges();

expect(datePicker.onValueChanged.emit).toHaveBeenCalled();
expect(datePicker.onValueChanged.emit).toHaveBeenCalledWith(valueChangedArgs);
expect(datePicker.value).toEqual(null);
expect(input.nativeElement.innerText).toEqual('');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export interface IDatePickerValidationFailedEventArgs {
prevValue: Date;
}

export interface IDatePickerValueChangedEventArgs {
oldValue: Date;
newValue: Date;
}

/**
* This interface is used to configure calendar format view options.
*/
Expand Down Expand Up @@ -622,6 +627,20 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
@Output()
public onSelection = new EventEmitter<Date>();

/**
*An @Output property that is fired when date picker value is changed.
*```typescript
*public valueChanged(event){
* alert("Date picker value is changed");
*}
*```
*```html
*<igx-date-picker (onValueChanged)="valueChanged($event)" mode="dropdown"></igx-date-picker>
*```
*/
@Output()
public onValueChanged = new EventEmitter<IDatePickerValueChangedEventArgs>();

/**
*An @Output property that fires when the user types/spins to a disabled date in the date-picker editor.
*```typescript
Expand Down Expand Up @@ -916,7 +935,15 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
* @memberOf {@link IgxDatePickerComponent}
*/
public selectDate(date: Date): void {
const oldDate = this.value;
this.value = date;
if ((oldDate && oldDate.getTime()) !== (this.value && this.value.getTime())) {
const args: IDatePickerValueChangedEventArgs = {
oldValue: oldDate,
newValue: this.value
};
this.onValueChanged.emit(args);
}
this.onSelection.emit(date);
this._onChangeCallback(date);
}
Expand All @@ -933,7 +960,17 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
* @memberOf {@link IgxDatePickerComponent}
*/
public deselectDate(): void {
const oldValue = this.value;
this.value = null;

if (oldValue !== null) {
const args: IDatePickerValueChangedEventArgs = {
oldValue: oldValue,
newValue: null
};
this.onValueChanged.emit(args);
}

if (this.calendar) {
this.calendar.deselectDate();
}
Expand Down Expand Up @@ -1025,8 +1062,17 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
date.setSeconds(this.value.getSeconds());
date.setMilliseconds(this.value.getMilliseconds());
}

const oldValue = this.value;
this.value = date;

if ((oldValue && oldValue.getTime()) !== (this.value && this.value.getTime())) {
const args: IDatePickerValueChangedEventArgs = {
oldValue: oldValue,
newValue: this.value
};
this.onValueChanged.emit(args);
}

this.calendar.viewDate = date;
this._onChangeCallback(date);
this.closeCalendar();
Expand Down Expand Up @@ -1162,9 +1208,17 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor

if (this.disabledDates === null
|| (this.disabledDates !== null && !isDateInRanges(newValue, this.disabledDates))) {
this.value = newValue;
this.invalidDate = '';
this._onChangeCallback(newValue);
const oldValue = this.value;
this.value = newValue;
if ((this.value && this.value.getTime()) !== (oldValue && oldValue.getTime())) {
const args: IDatePickerValueChangedEventArgs = {
oldValue: oldValue,
newValue: this.value
};
this.onValueChanged.emit(args);
}
this.invalidDate = '';
this._onChangeCallback(newValue);
} else {
const args: IDatePickerDisabledDateEventArgs = {
datePicker: this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
[igxFocus]="focused" [disableRipple]="true"></igx-checkbox>
</ng-container>
<ng-container *ngIf="column.dataType === 'date'">
<igx-date-picker [style.width.%]="100" [outlet]="grid.outletDirective" mode="dropdown" (onSelection)="editValue = $event"
<igx-date-picker [style.width.%]="100" [outlet]="grid.outletDirective" mode="dropdown" (onValueChanged)="editValue = $event.newValue"
[locale]="grid.locale" [value]="editValue" [igxFocus]="focused" [labelVisibility]="false">
</igx-date-picker>
</ng-container>
Expand Down
47 changes: 47 additions & 0 deletions projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,53 @@ describe('IgxGrid - Cell component', () => {
expect(cell.value.getTime()).toBe(selectedDate.getTime());
});

it('should be able to change value form date picker input-- date', () => {
const cell = grid.getCellByColumn(0, 'birthday');
const cellDomDate = fixture.debugElement.queryAll(By.css(CELL_CSS_CLASS))[3];
const selectedDate = new Date('04/12/2017');
const editValue = '04/12/2017';

cellDomDate.triggerEventHandler('dblclick', {});
fixture.detectChanges();

expect(cell.editMode).toBe(true);
const datePicker = cellDomDate.query(By.css('igx-date-picker')).componentInstance;
expect(datePicker).toBeDefined();

const editTemplate = cellDomDate.query(By.css('.igx-date-picker__input-date'));
UIInteractions.sendInput(editTemplate, editValue);
fixture.detectChanges();

expect(datePicker.value).toEqual(selectedDate);
UIInteractions.triggerKeyDownEvtUponElem('enter', cellDomDate.nativeElement, true);
fixture.detectChanges();

expect(cell.editMode).toBe(false);
expect(cell.value.getTime()).toEqual(selectedDate.getTime());
});

it('should be able to clear value -- date', () => {
const cell = grid.getCellByColumn(0, 'birthday');
const cellDomDate = fixture.debugElement.queryAll(By.css(CELL_CSS_CLASS))[3];

cellDomDate.triggerEventHandler('dblclick', {});
fixture.detectChanges();

expect(cell.editMode).toBe(true);
const datePicker = cellDomDate.query(By.css('igx-date-picker')).componentInstance;
expect(datePicker).toBeDefined();

const clear = cellDomDate.queryAll(By.css('.igx-icon'))[1];
UIInteractions.clickElement(clear);

expect(datePicker.value).toBeNull();
UIInteractions.triggerKeyDownEvtUponElem('enter', cellDomDate.nativeElement, true);
fixture.detectChanges();

expect(cell.editMode).toBe(false);
expect(cell.value).toBeNull();
});

it('should exit edit mode on filtering', () => {
let cell = grid.getCellByColumn(0, 'fullName');
const cellDom = fixture.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<igx-checkbox (change)="editValue = $event.checked" [value]="editValue" [checked]="editValue" [disableRipple]="true"></igx-checkbox>
</ng-container>
<ng-container *ngIf="column.dataType === 'date'">
<igx-date-picker [style.width.%]="100" [outlet]="grid.outletDirective" mode="dropdown" (onSelection)="editValue = $event"
<igx-date-picker [style.width.%]="100" [outlet]="grid.outletDirective" mode="dropdown" (onValueChanged)="editValue = $event.newValue"
[locale]="grid.locale" [value]="editValue" [igxFocus]="focused" [labelVisibility]="false">
</igx-date-picker>
</ng-container>
Expand Down

0 comments on commit a43a114

Please sign in to comment.