diff --git a/CHANGELOG.md b/CHANGELOG.md index dae6e5d7f82..143b62534f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,33 @@ # Ignite UI for Angular Change Log All notable changes for each version of this project will be documented in this file. -## 7.3.1 -`igx-core()` now includes some styles for printing layout. In order to turn them off, you need to pass an argument and set it to `false` +## 7.3.4 -``` -@include igx-core($print-layout: false); -``` +- `igxTimePicker` changes + - `onClosing` event is added. + - **Breaking Change** `onOpen` event is renamed to `onOpened`. + - **Breaking Change** `onClose` event is renamed to `onClosed`. + - **Behavioral Change** - action buttons are now available in the dropdown mode. + - **Feature** `IgxTimePickerComponent` now provides the ability for adding custom action buttons. Read up more information in the [ReadMe](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/src/lib/time-picker/README.md) + +- `igxDatePicker` changes + - `onClosing` event is added. + - **Breaking Change** `onOpen` event is renamed to `onOpened`. + - **Breaking Change** `onClose` event is renamed to `onClosed`. + - **Behavioral Change** - action buttons are now available in the dropdown mode. + - **Feature** `IgxDatePickerComponent` now provides the ability for adding custom action buttons. Read up more information in the [ReadMe](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/src/lib/date-picker/README.md) + + +## 7.3.3 + +- `igx-core()` now includes some styles for printing layout. +In order to turn them off, you need to pass an argument and set it to `false` + ``` + @include igx-core($print-layout: false); + ``` + +- `Pager` + - **Behavioral Change** - The pager is now hidden when there are no records in the grid. ## 7.3.1 - `IgxGrid` Custom keyboard navigation diff --git a/projects/igniteui-angular/migrations/migration-collection.json b/projects/igniteui-angular/migrations/migration-collection.json index 85db119c69a..3f8599e3284 100644 --- a/projects/igniteui-angular/migrations/migration-collection.json +++ b/projects/igniteui-angular/migrations/migration-collection.json @@ -40,6 +40,11 @@ "version": "7.2.0", "description": "Updates Ignite UI for Angular from v7.0.2 to v7.2.0", "factory": "./update-7_2_0" + }, + "migration-09": { + "version": "7.3.4", + "description": "Updates Ignite UI for Angular from v7.2.0 to v7.3.4", + "factory": "./update-7_3_4" } } } diff --git a/projects/igniteui-angular/migrations/update-7_3_4/changes/outputs.json b/projects/igniteui-angular/migrations/update-7_3_4/changes/outputs.json new file mode 100644 index 00000000000..1d7e4abeda9 --- /dev/null +++ b/projects/igniteui-angular/migrations/update-7_3_4/changes/outputs.json @@ -0,0 +1,37 @@ +{ + "$schema": "../../common/schema/binding.schema.json", + "changes": [ + { + "name": "onOpen", + "replaceWith": "onOpened", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onClose", + "replaceWith": "onClosed", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onOpen", + "replaceWith": "onOpened", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onClose", + "replaceWith": "onClosed", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + } + ] +} \ No newline at end of file diff --git a/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts b/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts new file mode 100644 index 00000000000..d54f995e82f --- /dev/null +++ b/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts @@ -0,0 +1,54 @@ +import * as path from 'path'; + +// tslint:disable:no-implicit-dependencies +import { virtualFs } from '@angular-devkit/core'; +import { EmptyTree } from '@angular-devkit/schematics'; +// tslint:disable-next-line:no-submodule-imports +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; + +describe('Update 7.3.4', () => { + let appTree: UnitTestTree; + const schematicRunner = new SchematicTestRunner('ig-migrate', path.join(__dirname, '../migration-collection.json')); + const configJson = { + defaultProject: 'testProj', + projects: { + testProj: { + sourceRoot: '/testSrc' + } + }, + schematics: { + '@schematics/angular:component': { + prefix: 'appPrefix' + } + } + }; + + beforeEach(() => { + appTree = new UnitTestTree(new EmptyTree()); + appTree.create('/angular.json', JSON.stringify(configJson)); + }); + + it('should update time picker events', done => { + appTree.create( + '/testSrc/appPrefix/component/test.component.html', + `` + ); + const tree = schematicRunner.runSchematic('migration-09', {}, appTree); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual( + ``); + done(); + }); + + it('should update date picker events', done => { + appTree.create( + '/testSrc/appPrefix/component/test.component.html', + `` + ); + const tree = schematicRunner.runSchematic('migration-09', {}, appTree); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual( + ``); + done(); + }); +}); diff --git a/projects/igniteui-angular/migrations/update-7_3_4/index.ts b/projects/igniteui-angular/migrations/update-7_3_4/index.ts new file mode 100644 index 00000000000..6cd57d63120 --- /dev/null +++ b/projects/igniteui-angular/migrations/update-7_3_4/index.ts @@ -0,0 +1,25 @@ +import * as path from 'path'; + +// tslint:disable:no-implicit-dependencies +import { normalize } from '@angular-devkit/core'; +import { + chain, + Rule, + SchematicContext, + SchematicsException, + Tree +} from '@angular-devkit/schematics'; +import { filterSourceDirs } from '../common/filterSourceDirs'; +import { getImportModulePositions } from '../common/tsUtils'; +import { UpdateChanges } from '../common/UpdateChanges'; + +const version = '7.3.4'; + +export default function(): Rule { + return (host: Tree, context: SchematicContext) => { + context.logger.info(`Applying migration for Ignite UI for Angular to version ${version}`); + + const update = new UpdateChanges(__dirname, host, context); + update.applyChanges(); + }; +} \ No newline at end of file diff --git a/projects/igniteui-angular/src/lib/date-picker/README.md b/projects/igniteui-angular/src/lib/date-picker/README.md index 5d53a7a3389..11e22fce03f 100644 --- a/projects/igniteui-angular/src/lib/date-picker/README.md +++ b/projects/igniteui-angular/src/lib/date-picker/README.md @@ -88,6 +88,21 @@ In order to re-template a date picker in `dropdown` mode, an element should be m ``` +The DatePicker action buttons could be retemplated. +```html + + +
+ +
+
+
+``` +```typescript + public selectToday(picker: IgxDatePickerComponent) { + picker.calendar.value = picker.calendar.viewDate = new Date(Date.now()); + } +``` # API diff --git a/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.html b/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.html index f439f6e1880..ae1d662b01f 100644 --- a/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.html +++ b/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.html @@ -1,10 +1,14 @@ - -
- - + +
+ + +
+
+
+ +
\ No newline at end of file diff --git a/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.ts b/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.ts index e34b153f897..06be516049c 100644 --- a/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.ts +++ b/projects/igniteui-angular/src/lib/date-picker/calendar-container.component.ts @@ -1,6 +1,7 @@ import { Component, ViewChild, Input, Output, EventEmitter, HostListener, HostBinding } from '@angular/core'; import { IgxCalendarComponent } from '../calendar'; import { InteractionMode } from '../core/enums'; +import { IgxDatePickerActionsDirective } from './date-picker.directives'; /** * @hidden @@ -26,6 +27,9 @@ export class IgxCalendarContainerComponent { @Input() public todayButtonLabel: string; + @Input() + public datePickerActions: IgxDatePickerActionsDirective; + @Output() public onClose = new EventEmitter(); diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts index 40689980770..65426ad111b 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts @@ -277,6 +277,10 @@ describe('IgxDatePicker', () => { const picker = document.getElementsByClassName('igx-calendar-picker'); const formattedSubHeaderText = (picker[0].children[1] as HTMLElement).innerText; expect(formattedSubHeaderText).toBe('2019/Oct'); + + const buttons = document.getElementsByClassName('igx-button--flat'); + expect(buttons.length).toEqual(1); + expect((buttons[0]as HTMLElement).innerText).toBe('TEST'); }); it('Retemplated calendar in date picker - dropdown mode', () => { @@ -295,6 +299,10 @@ describe('IgxDatePicker', () => { const picker = document.getElementsByClassName('igx-calendar-picker'); const formattedSubHeaderText = (picker[0].children[1] as HTMLElement).innerText; expect(formattedSubHeaderText).toBe('2019/Oct'); + + const buttons = document.getElementsByClassName('igx-button--flat'); + expect(buttons.length).toEqual(1); + expect((buttons[0]as HTMLElement).innerText).toBe('TEST'); }); it('locale propagate calendar value (de-DE)', () => { @@ -1197,6 +1205,9 @@ export class IgxDatePickerEditableComponent { {{ format.year.combined }}/ {{ format.month.combined | titlecase }} + + + ` }) diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts index 47d54023581..02ed7d76588 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts @@ -50,12 +50,12 @@ import { } from './date-picker.utils'; import { DatePickerDisplayValuePipe, DatePickerInputValuePipe } from './date-picker.pipes'; import { IDatePicker } from './date-picker.common'; -import { KEYS } from '../core/utils'; -import { IgxDatePickerTemplateDirective } from './date-picker.directives'; +import { KEYS, CancelableBrowserEventArgs } from '../core/utils'; +import { IgxDatePickerTemplateDirective, IgxDatePickerActionsDirective } from './date-picker.directives'; import { IgxCalendarContainerComponent } from './calendar-container.component'; import { InteractionMode } from '../core/enums'; -import { getViewportRect } from '../services/overlay/utilities'; import { fadeIn, fadeOut } from '../animations/fade'; +import { DeprecateProperty } from '../core/deprecateDecorators'; let NEXT_ID = 0; @@ -539,6 +539,7 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor public outlet: IgxOverlayOutletDirective | ElementRef; /** + * @deprecated Use 'onOpened' instead. *An event that is emitted when the `IgxDatePickerComponent` calendar is opened. *```typescript *public open(event){ @@ -549,10 +550,18 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor * *``` */ + @DeprecateProperty(`'onOpen' @Output property is deprecated. Use 'onOpened' instead.`) @Output() public onOpen = new EventEmitter(); /** + *An event that is emitted when the `IgxDatePickerComponent` calendar is opened. + */ + @Output() + public onOpened = new EventEmitter(); + + /** + * @deprecated Use 'onClosed' instead. *"An event that is emitted when the `IgxDatePickerComponent` is closed. *```typescript *public close(event){ @@ -563,8 +572,22 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor * *``` */ + @DeprecateProperty(`'onClose' @Output property is deprecated. Use 'onClosed' instead.`) @Output() public onClose = new EventEmitter(); + + /** + *An event that is emitted after the `IgxDatePickerComponent` is closed. + */ + @Output() + public onClosed = new EventEmitter(); + + /** + * An event that is emitted when the `IgxDatePickerComponent` is being closed. + */ + @Output() + public onClosing = new EventEmitter(); + /** *An @Output property that is fired when selection is made in the calendar. *```typescript @@ -673,6 +696,12 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor @ContentChild(IgxCalendarSubheaderTemplateDirective, { read: IgxCalendarSubheaderTemplateDirective }) public subheaderTemplate: IgxCalendarSubheaderTemplateDirective; + /** + *@hidden + */ + @ContentChild(IgxDatePickerActionsDirective, { read: IgxDatePickerActionsDirective }) + public datePickerActionsDirective: IgxDatePickerActionsDirective; + public calendar: IgxCalendarComponent; public hasHeader = true; public collapsed = true; @@ -804,6 +833,12 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor this._onClosed(); }); + this._overlayService.onClosing.pipe( + filter(overlay => overlay.id === this._componentID), + takeUntil(this._destroy$)).subscribe((event) => { + this.onClosing.emit(event); + }); + if (this.mode === InteractionMode.DropDown) { this.dateFormatParts = DatePickerUtil.parseDateFormat(this.mask, this.locale); if (this.mask === undefined) { @@ -1159,6 +1194,9 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor private _onOpened(event): void { this._onTouchedCallback(); + this.onOpened.emit(this); + + // TODO: remove this line after deprecating 'onOpen' this.onOpen.emit(this); if (this.calendar) { @@ -1169,6 +1207,9 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor private _onClosed(): void { this.collapsed = true; this._componentID = null; + this.onClosed.emit(this); + + // TODO: remove this line after deprecating 'onClose' this.onClose.emit(this); if (this.getEditElement()) { @@ -1200,6 +1241,7 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor componentInstance.vertical = isVertical; componentInstance.cancelButtonLabel = this.cancelButtonLabel; componentInstance.todayButtonLabel = this.todayButtonLabel; + componentInstance.datePickerActions = this.datePickerActionsDirective; componentInstance.onClose.pipe(takeUntil(this._destroy$)).subscribe(() => this.closeCalendar()); componentInstance.onTodaySelection.pipe(takeUntil(this._destroy$)).subscribe(() => this.triggerTodaySelection()); @@ -1265,9 +1307,10 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor * @hidden */ @NgModule({ - declarations: [IgxDatePickerComponent, IgxCalendarContainerComponent, + declarations: [IgxDatePickerComponent, IgxCalendarContainerComponent, IgxDatePickerActionsDirective, IgxDatePickerTemplateDirective, DatePickerDisplayValuePipe, DatePickerInputValuePipe], - exports: [IgxDatePickerComponent, IgxDatePickerTemplateDirective, DatePickerDisplayValuePipe, DatePickerInputValuePipe], + exports: [IgxDatePickerComponent, IgxDatePickerTemplateDirective, IgxDatePickerActionsDirective, + DatePickerDisplayValuePipe, DatePickerInputValuePipe], imports: [CommonModule, IgxIconModule, IgxInputGroupModule, IgxCalendarModule, IgxButtonModule, IgxRippleModule, IgxMaskModule], entryComponents: [IgxCalendarContainerComponent] }) diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.directives.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.directives.ts index a227875a82d..dcc9e536f55 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.directives.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.directives.ts @@ -12,3 +12,13 @@ import { Directive, TemplateRef } from '@angular/core'; export class IgxDatePickerTemplateDirective { constructor(public template: TemplateRef) { } } + +/** + * IgxDatePickerActionsDirective can be used to re-template the dropdown/dialog action buttons. + */ +@Directive({ + selector: '[igxDatePickerActions]' +}) +export class IgxDatePickerActionsDirective { + constructor(public template: TemplateRef) { } +} diff --git a/projects/igniteui-angular/src/lib/time-picker/README.md b/projects/igniteui-angular/src/lib/time-picker/README.md index 315688d1033..d45a379f051 100644 --- a/projects/igniteui-angular/src/lib/time-picker/README.md +++ b/projects/igniteui-angular/src/lib/time-picker/README.md @@ -107,6 +107,23 @@ or } ``` +The TimePicker action buttons could be retemplated. +```html + + +
+ +
+
+
+``` +```typescript + public selectToday(picker: IgxTimePickerComponent) { + picker.value = new Date(Date.now()); + picker.close(); + } +``` + # API ###### Inputs diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.common.ts b/projects/igniteui-angular/src/lib/time-picker/time-picker.common.ts index 27c1754834e..8bf45c7e5b8 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.common.ts +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.common.ts @@ -28,7 +28,7 @@ export interface IgxTimePickerBase { scrollHourIntoView(item: string): void; scrollMinuteIntoView(item: string): void; scrollAmPmIntoView(item: string): void; - hideOverlay(): void; + close(): void; parseMask(preserveAmPm?: boolean): string; } diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html index e148357a6fe..803e48486b8 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html @@ -24,6 +24,16 @@ + +
+ + +
+
@@ -44,13 +54,6 @@

{{ ampm }}

-
- - -
+
\ No newline at end of file diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.spec.ts b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.spec.ts index 680d1845176..618450b3bd5 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.spec.ts +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.spec.ts @@ -1416,14 +1416,84 @@ describe('IgxTimePicker', () => { expect(timePicker.onOpen.emit).toHaveBeenCalled(); })); - }); - describe('TimePicker DropDown retemplating', () => { - it('TimePicker with retemplated input group and dropDownTarget ref variable', fakeAsync(() => { - const fixture = TestBed.createComponent(IgxTimePickerRetemplatedDropDownComponent); + it('should display OK and Cancel buttons by default.', fakeAsync(() => { + fixture.detectChanges(); + + const iconTime = dom.queryAll(By.css('.igx-icon'))[0]; + + UIInteractions.clickElement(iconTime); + tick(); + fixture.detectChanges(); + + const buttons = document.getElementsByClassName('igx-time-picker__buttons')[0]; + expect(buttons.children.length).toEqual(2); + + const cancelBtn = buttons.children[0] as HTMLElement; + const okBtn = buttons.children[1] as HTMLElement; + + expect(cancelBtn.innerText).toBe('Cancel'); + expect(okBtn.innerText).toBe('OK'); + + const minuteColumn = dom.query(By.css('.igx-time-picker__minuteList')); + const keydownEvent = new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }); + + minuteColumn.nativeElement.dispatchEvent(keydownEvent); + fixture.detectChanges(); + + expect(minuteColumn.nativeElement.children[3].innerText).toEqual('50'); + + cancelBtn.click(); + tick(); fixture.detectChanges(); - const dom = fixture.debugElement; + const inputGroup = dom.query(By.directive(IgxInputDirective)); + expect(inputGroup.nativeElement.value).toEqual('05:45 PM'); + + UIInteractions.clickElement(iconTime); + tick(); + fixture.detectChanges(); + + minuteColumn.nativeElement.dispatchEvent(keydownEvent); + fixture.detectChanges(); + + okBtn.click(); + tick(); + fixture.detectChanges(); + + expect(inputGroup.nativeElement.value).toEqual('05:50 PM'); + + timePicker.okButtonLabel = ''; + timePicker.cancelButtonLabel = ''; + + UIInteractions.clickElement(iconTime); + tick(); + fixture.detectChanges(); + + expect(document.getElementsByClassName('igx-time-picker__buttons').length).toEqual(0); + })); + }); + + describe('TimePicker retemplating and customization', () => { + configureTestSuite(); + let fixture; + let dom; + + beforeEach( + async(() => { + fixture = TestBed.createComponent(IgxTimePickerRetemplatedDropDownComponent); + fixture.detectChanges(); + + dom = fixture.debugElement; + }) + ); + + afterEach(async(() => { + UIInteractions.clearOverlay(); + })); + + + it('TimePicker with retemplated input group and dropDownTarget ref variable', fakeAsync(() => { const icon = dom.query(By.css('.igx-icon')); const inputGroup = dom.query(By.css('.igx-input-group')); @@ -1445,6 +1515,27 @@ describe('IgxTimePicker', () => { expect(dropdownClientRect.top).toEqual(inputGroupClientRect.bottom); expect(dropdownClientRect.left).toEqual(inputGroupClientRect.left); })); + + it('should be able to add custom buttons.', fakeAsync(() => { + const iconTime = dom.queryAll(By.css('.igx-icon'))[0]; + + UIInteractions.clickElement(iconTime); + tick(); + fixture.detectChanges(); + + const buttons = document.getElementsByClassName('test')[0]; + expect(buttons.children.length).toEqual(1); + + const customBtn = buttons.children[0] as HTMLElement; + expect(customBtn.innerText).toBe('SELECT'); + + customBtn.click(); + tick(); + fixture.detectChanges(); + + const input = dom.query(By.directive(IgxInputDirective)); + expect(input.nativeElement.value).toEqual('10:45 AM'); + })); }); }); @@ -1605,8 +1696,8 @@ export class IgxTimePickerDropDownNoValueComponent { @Component({ -template: ` - + template: ` + @@ -1616,10 +1707,20 @@ template: ` + +
+ +
+
` }) -export class IgxTimePickerRetemplatedDropDownComponent { } +export class IgxTimePickerRetemplatedDropDownComponent { + public select(picker: IgxTimePickerComponent) { + picker.value = new Date(2018, 10, 27, 10, 45, 0, 0); + picker.close(); + } +} // helper functions function findByInnerText(collection, searchText) { diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts index 621a2d82dd1..eff3ac04a97 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts @@ -28,7 +28,8 @@ import { IgxHourItemDirective, IgxItemListDirective, IgxMinuteItemDirective, - IgxTimePickerTemplateDirective + IgxTimePickerTemplateDirective, + IgxTimePickerActionsDirective } from './time-picker.directives'; import { Subject, fromEvent, interval, animationFrameScheduler } from 'rxjs'; import { EditorProvider } from '../core/edit-provider'; @@ -43,8 +44,9 @@ import { IgxOverlayOutletDirective, IgxToggleModule, IgxToggleDirective } from ' import { TimeDisplayFormatPipe, TimeInputFormatPipe } from './time-picker.pipes'; import { ITimePickerResourceStrings, TimePickerResourceStringsEN } from '../core/i18n/time-picker-resources'; import { CurrentResourceStrings } from '../core/i18n/resources'; -import { KEYS } from '../core/utils'; +import { KEYS, CancelableBrowserEventArgs } from '../core/utils'; import { InteractionMode } from '../core/enums'; +import { DeprecateProperty } from '../core/deprecateDecorators'; let NEXT_ID = 0; @@ -204,7 +206,10 @@ export class IgxTimePickerComponent implements * An accessor that returns the label of ok button. */ get okButtonLabel(): string { - return this._okButtonLabel || this.resourceStrings.igx_time_picker_ok; + if (this._okButtonLabel === null) { + return this.resourceStrings.igx_time_picker_ok; + } + return this._okButtonLabel; } /** @@ -223,7 +228,10 @@ export class IgxTimePickerComponent implements * An accessor that returns the label of cancel button. */ get cancelButtonLabel(): string { - return this._cancelButtonLabel || this.resourceStrings.igx_time_picker_cancel; + if (this._cancelButtonLabel === null) { + return this.resourceStrings.igx_time_picker_cancel; + } + return this._cancelButtonLabel; } /** @@ -394,6 +402,7 @@ export class IgxTimePickerComponent implements public onValidationFailed = new EventEmitter(); /** + * @deprecated Use 'onOpened' instead. * Emitted when a timePicker is being opened. * ```html *@ViewChild("toast") @@ -408,15 +417,36 @@ export class IgxTimePickerComponent implements * * ``` */ + @DeprecateProperty(`'onOpen' @Output property is deprecated. Use 'onOpened' instead.`) @Output() public onOpen = new EventEmitter(); /** + * Emitted when a timePicker is opened. + */ + @Output() + public onOpened = new EventEmitter(); + + /** + * @deprecated Use 'onClosed' instead. * Emitted when a timePicker is being closed. */ + @DeprecateProperty(`'onClose' @Output property is deprecated. Use 'onClosed' instead.`) @Output() public onClose = new EventEmitter(); + /** + * Emitted when a timePicker is closed. + */ + @Output() + public onClosed = new EventEmitter(); + + /** + * Emitted when a timePicker is being closed. + */ + @Output() + public onClosing = new EventEmitter(); + /** * @hidden */ @@ -447,6 +477,12 @@ export class IgxTimePickerComponent implements @ContentChild(IgxTimePickerTemplateDirective, { read: IgxTimePickerTemplateDirective }) protected timePickerTemplateDirective: IgxTimePickerTemplateDirective; + /** + *@hidden + */ + @ContentChild(IgxTimePickerActionsDirective, { read: IgxTimePickerActionsDirective }) + public timePickerActionsDirective: IgxTimePickerActionsDirective; + /** * @hidden */ @@ -720,12 +756,22 @@ export class IgxTimePickerComponent implements this._onDropDownClosed(); } + this.onClosed.emit(this); + + // TODO: remove this line after deprecating 'onClose' this.onClose.emit(this); }); this.toggleRef.onOpened.pipe(takeUntil(this._destroy$)).subscribe(() => { + this.onOpened.emit(this); + + // TODO: remove this line after deprecating 'onOpen' this.onOpen.emit(this); }); + + this.toggleRef.onClosing.pipe(takeUntil(this._destroy$)).subscribe((event) => { + this.onClosing.emit(event); + }); } } @@ -1384,7 +1430,7 @@ export class IgxTimePickerComponent implements public okButtonClick(): boolean { const time = this._getSelectedTime(); if (this._isValueValid(time)) { - this.hideOverlay(); + this.close(); this.value = time; return true; } else { @@ -1407,7 +1453,11 @@ export class IgxTimePickerComponent implements * ``` */ public cancelButtonClick(): void { - this.hideOverlay(); + if (this.mode === InteractionMode.DropDown) { + this.displayValue = this._formatTime(this.value, this.format); + } + + this.close(); this.selectedHour = this._prevSelectedHour; this.selectedMinute = this._prevSelectedMinute; @@ -1457,9 +1507,16 @@ export class IgxTimePickerComponent implements } /** - * @hidden + * Closes the dropdown/dialog. + * ```html + * + * ``` + * ```typescript + * @ViewChild('timePicker', { read: IgxTimePickerComponent }) picker: IgxTimePickerComponent; + * picker.close(); + * ``` */ - public hideOverlay(): void { + public close(): void { this.toggleRef.close(); } @@ -1494,7 +1551,7 @@ export class IgxTimePickerComponent implements this.onValueChanged.emit(args); } } else { - this.hideOverlay(); + this.close(); } } @@ -1644,12 +1701,14 @@ export class IgxTimePickerComponent implements IgxMinuteItemDirective, IgxAmPmItemDirective, IgxTimePickerTemplateDirective, + IgxTimePickerActionsDirective, TimeDisplayFormatPipe, TimeInputFormatPipe ], exports: [ IgxTimePickerComponent, IgxTimePickerTemplateDirective, + IgxTimePickerActionsDirective, TimeDisplayFormatPipe, TimeInputFormatPipe ], diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts b/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts index ad5d9f001d6..22a3428b4d4 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts @@ -157,7 +157,7 @@ export class IgxItemListDirective { event.preventDefault(); if (this.timePicker.mode === InteractionMode.DropDown) { - this.timePicker.hideOverlay(); + this.timePicker.close(); return; } this.timePicker.okButtonClick(); @@ -345,3 +345,12 @@ export class IgxTimePickerTemplateDirective { constructor(public template: TemplateRef) { } } +/** + * This directive can be used to add custom action buttons to the dropdownb/dialog. + */ +@Directive({ + selector: '[igxTimePickerActions]' +}) +export class IgxTimePickerActionsDirective { + constructor(public template: TemplateRef) { } +} diff --git a/src/app/date-picker/date-picker.sample.html b/src/app/date-picker/date-picker.sample.html index a1d7ab8d7f5..a71484ea949 100644 --- a/src/app/date-picker/date-picker.sample.html +++ b/src/app/date-picker/date-picker.sample.html @@ -55,6 +55,11 @@

DropDown Date Picker

+ +
+ +
+
@@ -74,11 +79,17 @@

DropDown Date Picker

DropDown Date Picker bind with ngModel

isSpinLoop set to false

- + - +
diff --git a/src/app/date-picker/date-picker.sample.css b/src/app/date-picker/date-picker.sample.scss similarity index 66% rename from src/app/date-picker/date-picker.sample.css rename to src/app/date-picker/date-picker.sample.scss index 20f3da798cf..6420ac759bb 100644 --- a/src/app/date-picker/date-picker.sample.css +++ b/src/app/date-picker/date-picker.sample.scss @@ -6,3 +6,9 @@ margin: 16px; width: 200px; } + +.action-buttons { + display: flex; + flex-flow: column; + margin: 10px; +} diff --git a/src/app/date-picker/date-picker.sample.ts b/src/app/date-picker/date-picker.sample.ts index d724508ecea..c6049c83dd0 100644 --- a/src/app/date-picker/date-picker.sample.ts +++ b/src/app/date-picker/date-picker.sample.ts @@ -8,7 +8,7 @@ import { DatePipe, formatDate } from '@angular/common'; @Component({ selector: 'app-date-picker-sample', - styleUrls: ['date-picker.sample.css'], + styleUrls: ['date-picker.sample.scss'], templateUrl: 'date-picker.sample.html' }) @@ -76,4 +76,8 @@ export class DatePickerSampleComponent { const parsedDate = (input !== '') ? new Date(input) : ''; this.retemplatedDP.value = parsedDate; } + + public selectToday(picker: IgxDatePickerComponent) { + picker.calendar.value = picker.calendar.viewDate = new Date(Date.now()); + } } diff --git a/src/app/time-picker/time-picker.sample.html b/src/app/time-picker/time-picker.sample.html index 4d28fb95800..2d0064f3141 100644 --- a/src/app/time-picker/time-picker.sample.html +++ b/src/app/time-picker/time-picker.sample.html @@ -31,7 +31,7 @@

Vertical Time Picker

24h Time Picker

24h Time Format

- +
@@ -76,7 +76,7 @@

Templated Time Picker

Templated Time Picker

Time picker with dropdown mode

- + @@ -90,9 +90,9 @@

Templated Time Picker

Templated Time Picker

-

Time picker with dropdown mode + overlay settings

+

Time picker with dropdown mode + overlay settings + custom buttons

- + @@ -101,6 +101,11 @@

Templated Time Picker

+ +
+ +
+
diff --git a/src/app/time-picker/time-picker.sample.css b/src/app/time-picker/time-picker.sample.scss similarity index 65% rename from src/app/time-picker/time-picker.sample.css rename to src/app/time-picker/time-picker.sample.scss index 3cb6a86e56b..6cf8b6d4516 100644 --- a/src/app/time-picker/time-picker.sample.css +++ b/src/app/time-picker/time-picker.sample.scss @@ -5,4 +5,10 @@ align-content: flex-start; margin: 16px; width: 200px; +} + +.action-buttons { + display: flex; + flex-flow: column; + margin: 10px; } \ No newline at end of file diff --git a/src/app/time-picker/time-picker.sample.ts b/src/app/time-picker/time-picker.sample.ts index d6528deb8d6..0581efd9af5 100644 --- a/src/app/time-picker/time-picker.sample.ts +++ b/src/app/time-picker/time-picker.sample.ts @@ -3,7 +3,7 @@ import { IgxTimePickerComponent, InteractionMode, IgxInputDirective, AutoPositio @Component({ selector: 'app-time-picker-sample', - styleUrls: ['time-picker.sample.css'], + styleUrls: ['time-picker.sample.scss'], templateUrl: 'time-picker.sample.html' }) export class TimePickerSampleComponent implements AfterViewInit { @@ -17,6 +17,7 @@ export class TimePickerSampleComponent implements AfterViewInit { mode = InteractionMode.DropDown; date = new Date(2018, 10, 27, 17, 45, 0, 0); + val = new Date(0, 0, 0, 19, 35, 0, 0); today = new Date(Date.now()); isRequired = true; @@ -60,4 +61,9 @@ export class TimePickerSampleComponent implements AfterViewInit { timePickerValue.setHours(parts[0], parts[1]); } } + + public selectToday(picker: IgxTimePickerComponent) { + picker.value = new Date(Date.now()); + picker.close(); + } }