From 63a54eb32b546ab31dc37135c1f91dff3c951133 Mon Sep 17 00:00:00 2001 From: Nikolay Alipiev Date: Mon, 19 Apr 2021 17:09:37 +0300 Subject: [PATCH] feat(date-time-editor, pickers): add migrations, changelog, readme #6482, #6483 (#9319) Co-authored-by: Boris Co-authored-by: plamenamiteva --- CHANGELOG.md | 48 + .../update-12_0_0/changes/inputs.json | 176 +++ .../update-12_0_0/changes/members.json | 200 ++++ .../update-12_0_0/changes/outputs.json | 152 +++ .../migrations/update-12_0_0/index.spec.ts | 1046 +++++++++++++++++ .../migrations/update-12_0_0/index.ts | 110 ++ .../src/lib/date-picker/README.md | 169 ++- .../src/lib/date-picker/date-picker.common.ts | 10 - .../lib/date-picker/date-picker.component.ts | 25 +- .../src/lib/date-range-picker/README.md | 23 +- .../date-range-picker.component.ts | 11 - .../src/lib/time-picker/README.md | 143 +-- 12 files changed, 1873 insertions(+), 240 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2549eb8cd1..f0632f29c75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,54 @@ All notable changes for each version of this project will be documented in this - `IgxDateTimeEditor` - `spinDelta` input property which allows a user to provide different delta values that will be used for spinning. All parts default to `1`. - `increment` and `decrement` methods now accept an optional `delta` parameter which targets the currently spun date portion. It takes precedence over the values set in `spinDelta`. + - **Breaking Change** - `isSpinLoop` property is renamed to `spinLoop`. + - **Breaking Change** - `onValueChange` event is renamed to `valueChange` +- `IgxDatePicker` + - **Breaking Change** - new way to define custom elements in the `igx-date-picker` while the following properties are deleted or deprecated: `formatter`, `context`, `labelInternal`, `template`. + ```html + + + + calendar_view_day + + + delete + + + ``` + - **Breaking Change** - `mode` and `format` are replaced by `inputFormat`. + - **Breaking Change** - `editorTabIndex` is renamed to `tabIndex`. + - **Breaking Change** - `monthsViewNumber` is renamed to `displayMonthsCount`. + - **Breaking Change** - `vertical` is renamed to `headerOrientation`. + - **Breaking Change** - `displayData` is renamed to `displayFormat`. + - **Breaking Change** - `dropDownOverlaySettings` and `modalOverlaySettings` are replaced by the `overlaySettings`. + - **Breaking Change** - `onSelection` event is renamed to `valueChange`. + - **Breaking Change** - `onValidationFailed` event is renamed to `validationFailed`. + - **Breaking Change** - `onDisabledDate` event is removed. + - **Breaking Change** - `onOpening`, `onOpened`, `onClosing` and `onClosed` events are renamed respectively to `opening`, `opened`, `closing` and `closed`. +- `IgxTimePicker` + - **Breaking Change** - new way to define custom elements in the `igx-time-picker` while the following properties are deleted or deprecated: `context`, `promptChar`, `displayTime`, `template`. + ```html + + + + alarm + + + delete + + + ``` + - **Breaking Change** - `format` is replaced by `inputFormat`. + - **Breaking Change** - `isSpinLoop` property is renamed to `spinLoop`. + - **Breaking Change** - `vertical` is renamed to `headerOrientation`. + - **Breaking Change** - `onValueChanged` event is renamed to `valueChange`. + - **Breaking Change** - `onOpening`, `onOpened`, `onClosing` and `onClosed` events are renamed respectively to `opening`, `opened`, `closing` and `closed`. + - **Breaking Change** - `onValidationFailed` event is renamed to `validationFailed`. +- `IgxDateRangePicker` + - **Breaking Change** - `monthsViewNumber` is renamed to `displayMonthsCount`. + - **Breaking Change** - `rangeSelected` event is renamed to `valueChange`. + - **Breaking Change** - `onOpening`, `onOpened`, `onClosing` and `onClosed` events are renamed respectively to `opening`, `opened`, `closing` and `closed`. - `IgxForOf`, `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid` - **Behavioral Change** - Virtual containers now scroll smoothly when using the mouse wheel(s) to scroll them horizontally or vertically. This behavior more closely resembles the scrolling behavior of non-virtualized containers in most modern browsers. - `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid` diff --git a/projects/igniteui-angular/migrations/update-12_0_0/changes/inputs.json b/projects/igniteui-angular/migrations/update-12_0_0/changes/inputs.json index 011d470b306..ce086bb2290 100644 --- a/projects/igniteui-angular/migrations/update-12_0_0/changes/inputs.json +++ b/projects/igniteui-angular/migrations/update-12_0_0/changes/inputs.json @@ -88,6 +88,182 @@ "selector": "igx-bottom-nav-item", "type": "component" } + }, + { + "name": "isSpinLoop", + "replaceWith": "spinLoop", + "owner": { + "selector": "igxDateTimeEditor", + "type": "directive" + } + }, + { + "name": "editorTabIndex", + "replaceWith": "tabIndex", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "labelVisibility", + "remove": true, + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "mask", + "replaceWith": "inputFormat", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "monthsViewNumber", + "replaceWith": "displayMonthsCount", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "vertical", + "replaceWith": "headerOrientation", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "context", + "remove": true, + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "displayData", + "replaceWith": "displayFormat", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "format", + "replaceWith": "inputFormat", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "dropDownOverlaySettings", + "replaceWith": "overlaySettings", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "modalOverlaySettings", + "replaceWith": "overlaySettings", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "labelInternal", + "remove": true, + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "template", + "remove": true, + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "isSpinLoop", + "replaceWith": "spinLoop", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "vertical", + "replaceWith": "headerOrientation", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "context", + "remove": true, + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "template", + "remove": true, + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "promptChar", + "remove": true, + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "displayTime", + "remove": true, + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "labelVisibility", + "remove": true, + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "format", + "replaceWith": "inputFormat", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "monthsViewNumber", + "replaceWith": "displayMonthsCount", + "owner": { + "selector": "igx-date-range-picker", + "type": "component" + } } ] } diff --git a/projects/igniteui-angular/migrations/update-12_0_0/changes/members.json b/projects/igniteui-angular/migrations/update-12_0_0/changes/members.json index dc81bef6c46..84d1a3f6f65 100644 --- a/projects/igniteui-angular/migrations/update-12_0_0/changes/members.json +++ b/projects/igniteui-angular/migrations/update-12_0_0/changes/members.json @@ -97,6 +97,206 @@ "definedIn": [ "IgxGridForOfDirective" ] + }, + { + "member": "isSpinLoop", + "replaceWith": "spinLoop", + "definedIn": [ + "IgxDateTimeEditorDirective", + "IgxTimePickerComponent" + ] + }, + { + "member": "onValueChange", + "replaceWith": "valueChange", + "definedIn": [ + "IgxDateTimeEditorDirective" + ] + }, + { + "member": "selectDate", + "replaceWith": "select", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "triggerTodaySelection", + "replaceWith": "selectToday", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "deselectDate", + "replaceWith": "clear", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "openDialog", + "replaceWith": "open", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "editorTabIndex", + "replaceWith": "tabIndex", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "mask", + "replaceWith": "inputFormat", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "monthsViewNumber", + "replaceWith": "displayMonthsCount", + "definedIn": [ + "IgxDatePickerComponent", + "IgxRangePickerComponent" + ] + }, + { + "member": "vertical", + "replaceWith": "headerOrientation", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "displayData", + "replaceWith": "displayFormat", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "format", + "replaceWith": "inputFormat", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "dropDownOverlaySettings", + "replaceWith": "overlaySettings", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "modalOverlaySettings", + "replaceWith": "overlaySettings", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "onSelection", + "replaceWith": "valueChange", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "onClosing", + "replaceWith": "closing", + "definedIn": [ + "IgxDatePickerComponent", + "IgxTimePickerComponent", + "IgxRangePickerComponent" + ] + }, + { + "member": "onClosed", + "replaceWith": "closed", + "definedIn": [ + "IgxDatePickerComponent", + "IgxTimePickerComponent", + "IgxRangePickerComponent" + ] + }, + { + "member": "onOpening", + "replaceWith": "opening", + "definedIn": [ + "IgxDatePickerComponent", + "IgxTimePickerComponent", + "IgxRangePickerComponent" + ] + }, + { + "member": "onOpened", + "replaceWith": "opened", + "definedIn": [ + "IgxDatePickerComponent", + "IgxTimePickerComponent", + "IgxRangePickerComponent" + ] + }, + { + "member": "onValidationFailed", + "replaceWith": "validationFailed", + "definedIn": [ + "IgxDatePickerComponent" + ] + }, + { + "member": "okButtonClicked", + "replaceWith": "close", + "definedIn": [ + "IgxTimePickerComponent" + ] + }, + { + "member": "openDialog", + "replaceWith": "open", + "definedIn": [ + "IgxTimePickerComponent" + ] + }, + { + "member": "format", + "replaceWith": "inputFormat", + "definedIn": [ + "IgxTimePickerComponent" + ] + }, + { + "member": "onValueChanged", + "replaceWith": "valueChange", + "definedIn": [ + "IgxTimePickerComponent" + ] + }, + { + "member": "onValidationFailed", + "replaceWith": "validationFailed", + "definedIn": [ + "IgxTimePickerComponent" + ] + }, + { + "member": "selectRange", + "replaceWith": "select", + "definedIn": [ + "IgxRangePickerComponent" + ] + }, + { + "member": "rangeSelected", + "replaceWith": "valueChange", + "definedIn": [ + "IgxRangePickerComponent" + ] } ] } + diff --git a/projects/igniteui-angular/migrations/update-12_0_0/changes/outputs.json b/projects/igniteui-angular/migrations/update-12_0_0/changes/outputs.json index 291f942f93b..f0aa60157fc 100644 --- a/projects/igniteui-angular/migrations/update-12_0_0/changes/outputs.json +++ b/projects/igniteui-angular/migrations/update-12_0_0/changes/outputs.json @@ -152,6 +152,158 @@ "selector": "igx-column-actions", "type": "component" } + }, + { + "name": "onValueChange", + "replaceWith": "valueChange", + "owner": { + "selector": "igxDateTimeEditor", + "type": "directive" + } + }, + { + "name": "onSelection", + "replaceWith": "valueChange", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onClosing", + "replaceWith": "closing", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onClosed", + "replaceWith": "closed", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onOpening", + "replaceWith": "opening", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onOpened", + "replaceWith": "opened", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onDisabledDate", + "remove": true, + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onValidationFailed", + "replaceWith": "validationFailed", + "owner": { + "selector": "igx-date-picker", + "type": "component" + } + }, + { + "name": "onValueChanged", + "replaceWith": "valueChange", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onClosing", + "replaceWith": "closing", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onClosed", + "replaceWith": "closed", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onOpening", + "replaceWith": "opening", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onOpened", + "replaceWith": "opened", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onValidationFailed", + "replaceWith": "validationFailed", + "owner": { + "selector": "igx-time-picker", + "type": "component" + } + }, + { + "name": "onClosing", + "replaceWith": "closing", + "owner": { + "selector": "igx-date-range-picker", + "type": "component" + } + }, + { + "name": "onClosed", + "replaceWith": "closed", + "owner": { + "selector": "igx-date-range-picker", + "type": "component" + } + }, + { + "name": "onOpening", + "replaceWith": "opening", + "owner": { + "selector": "igx-date-range-picker", + "type": "component" + } + }, + { + "name": "onOpened", + "replaceWith": "opened", + "owner": { + "selector": "igx-date-range-picker", + "type": "component" + } + }, + { + "name": "rangeSelected", + "replaceWith": "valueChange", + "owner": { + "selector": "igx-date-range-picker", + "type": "component" + } } ] } diff --git a/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts index 09a9f410b0f..7cae6bc0c62 100644 --- a/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts @@ -337,6 +337,1052 @@ igx-bottom-nav-content { igx-bottom-nav-header { padding: 8px; }`); + + }); + + // IgxDateTimeEditor + it('should update isSpinLoop', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onValueChange', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + // IgxDatePicker + it('should update onSelection', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onClosing', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onClosed', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onOpening', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onOpened', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onValidationFailed', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should remove onDisabledDate', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update editorTabIndex', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should remove labelVisibility', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update mask', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update format', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update displayData', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update monthsViewNumber', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update vertical', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update dropDownOverlaySettings', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update modalOverlaySettings', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + // IgxTimePicker + it('should update onValueChanged', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onClosing', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onClosed', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onOpening', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onOpened', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onValidationFailed', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update isSpinLoop', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update vertical', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update format', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + // IgxDateRangePicker + it('should update rangeSelected', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onClosing', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onClosed', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onOpening', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update onOpened', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should update monthsViewNumber', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + // Custom migrations + + // igxDatePicker + it('should remove [mode]=dropdown and add default date label', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + it('should remove mode=dropdown', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should not remove [mode]=dialog', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should remove mode=dialog', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should add mode=dialog', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should remove label property and add it as a child elem', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + it('should remove label property and add it as a child elem (interpolation)', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + it('should remove label and labelVisibility properties and add it as a child elem (interpolation) with ngIf', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + // igxTimePicker + it('should remove [mode]=dropdown and add default time label', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + it('should remove mode=dropdown', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should not remove [mode]=dialog', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should remove mode=dialog', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should add mode=dialog', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + ` + ); + }); + + it('should remove label property and add it as a child elem', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + it('should remove label property and add it as a child elem (interpolation)', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); + }); + + it('should remove label and labelVisibility properties and add it as a child elem (interpolation) with ngIf', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner + .runSchematicAsync(migrationName, {}, appTree) + .toPromise(); + + expect( + tree.readContent('/testSrc/appPrefix/component/test.component.html') + ).toEqual( + ` + + + ` + ); }); it('Should update row component types with RowType', async () => { diff --git a/projects/igniteui-angular/migrations/update-12_0_0/index.ts b/projects/igniteui-angular/migrations/update-12_0_0/index.ts index 6568aef3591..7b80e926fb0 100644 --- a/projects/igniteui-angular/migrations/update-12_0_0/index.ts +++ b/projects/igniteui-angular/migrations/update-12_0_0/index.ts @@ -30,6 +30,26 @@ export default (): Rule => (host: Tree, context: SchematicContext) => { labelDirective: 'igxTabHeaderLabel' } ]; + + const EDITOR_COMPONENTS = [{ + COMPONENT: 'igx-date-picker', + TEMPLATE_DIRECTIVE: 'igxDatePickerTemplate', + TEMPLATE_WARN_MSG: +`\n\n` + }, { + COMPONENT: 'igx-time-picker', + TEMPLATE_DIRECTIVE: 'igxTimePickerTemplate', + TEMPLATE_WARN_MSG: +`\n\n` + }]; + const EDITORS_MODE = ['[mode]', 'mode']; + const EDITORS_LABEL = ['[label]', 'label']; + const EDITORS_LABEL_VISIBILITY = ['[labelVisibility]', 'labelVisibility']; + const update = new UpdateChanges(__dirname, host, context); const changes = new Map(); const htmlFiles = update.templateFiles; @@ -324,5 +344,95 @@ export default (): Rule => (host: Tree, context: SchematicContext) => { host.overwrite(entryPath, content); } + // igxDatePicker & igxTimePicker migrations + for (const comp of EDITOR_COMPONENTS) { + for (const path of htmlFiles) { + + // DatePicker and TimePicker don't support templates anymore. + // That is why migrations inserts a comment to notify the developer to remove the templates. + findElementNodes(parseFile(host, path), comp.COMPONENT) + .map(editor => findElementNodes([editor], 'ng-template')) + .reduce((prev, curr) => prev.concat(curr), []) + .filter(template => hasAttribute(template as Element, comp.TEMPLATE_DIRECTIVE)) + .map(node => getSourceOffset(node as Element)) + .forEach(offset => { + const { startTag, file } = offset; + addChange(file.url, new FileChange(startTag.start, comp.TEMPLATE_WARN_MSG)); + }); + + // DatePicker and TimePicker default mode is changed to dropdown. + // 1. That is why any occurrence of drop down mode is removed and + // 2. dialog mode is added for those that didn't explicitly set the mode prop. + + // 1. Remove dropdown mode + findElementNodes(parseFile(host, path), comp.COMPONENT) + .filter(template => hasAttribute(template as Element, EDITORS_MODE)) + .map(node => getSourceOffset(node as Element)) + .forEach(offset => { + const { file } = offset; + getAttribute(offset.node as Element, EDITORS_MODE).forEach(attr => { + const { sourceSpan, value } = attr; + if (value.replace(/'/g,'').replace(/"/g,'') === 'dropdown') { + const attrKeyValue = file.content.substring(sourceSpan.start.offset, sourceSpan.end.offset); + addChange(file.url, new FileChange(sourceSpan.start.offset, '', attrKeyValue, 'replace')); + } + }); + }); + + // 2. Insert dialog mode + findElementNodes(parseFile(host, path), comp.COMPONENT) + .filter(template => !hasAttribute(template as Element, EDITORS_MODE)) + .map(node => getSourceOffset(node as Element)) + .forEach(offset => { + const { startTag, file } = offset; + addChange(file.url, new FileChange(startTag.end - 1, ' mode="dialog"')); + }); + + + // Remove label property and project it as + // Check also labelVisibility value. + findElementNodes(parseFile(host, path), comp.COMPONENT) + .filter(template => hasAttribute(template as Element, EDITORS_LABEL)) + .map(node => getSourceOffset(node as Element)) + .forEach(offset => { + const { startTag, file } = offset; + let visibilityValue: string | boolean = true; + if (hasAttribute(offset.node as Element, EDITORS_LABEL_VISIBILITY)) { + const visibility = getAttribute(offset.node as Element, EDITORS_LABEL_VISIBILITY); + visibilityValue = visibility[0].value; + } + + getAttribute(offset.node as Element, EDITORS_LABEL).forEach(attr => { + const { sourceSpan, name, value } = attr; + const attrKeyValue = file.content.substring(sourceSpan.start.offset, sourceSpan.end.offset); + let label; + const ngIF = (typeof visibilityValue === 'boolean') ? `` : ` *ngIf="${visibilityValue}"`; + if (name.startsWith('[')) { + label = `\n`; + } else { + label = `\n`; + } + addChange(file.url, new FileChange(sourceSpan.start.offset, '', attrKeyValue, 'replace')); + addChange(file.url, new FileChange(startTag.end, label)); + }); + }); + + // If label and labelVisibility are not set this means that we should project default labels: "Date" & "Time" + findElementNodes(parseFile(host, path), comp.COMPONENT) + .filter(template => !hasAttribute(template as Element, EDITORS_LABEL) && + !hasAttribute(template as Element, EDITORS_LABEL_VISIBILITY)) + .map(node => getSourceOffset(node as Element)) + .forEach(offset => { + const { startTag, file } = offset; + addChange(file.url, + new FileChange(startTag.end, `\n`)); + }); + + applyChanges(); + changes.clear(); + } + } + + // Apply all selector and input changes update.applyChanges(); }; diff --git a/projects/igniteui-angular/src/lib/date-picker/README.md b/projects/igniteui-angular/src/lib/date-picker/README.md index 50abc3b296e..c921a7b5f4e 100644 --- a/projects/igniteui-angular/src/lib/date-picker/README.md +++ b/projects/igniteui-angular/src/lib/date-picker/README.md @@ -2,7 +2,7 @@ The **igx-date-picker** component allows you to choose date from calendar which is presented into input field. -A walkthrough of how to get started can be found [here](https://www.infragistics.com/products/ignite-ui-angular/angular/components/date_picker.html) +A walk through of how to get started can be found [here](https://www.infragistics.com/products/ignite-ui-angular/angular/components/date_picker.html) ## Dependencies In order to be able to use **igx-date-picker** you should keep in mind that it is dependent on **BrowserAnimationsModule**, @@ -10,111 +10,83 @@ which must be imported **only once** in your application's AppModule, for exampl ```typescript import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ - imports: [ - ... + imports: [ + ... BrowserAnimationsModule ... - ] + ] }) export class AppModule { } ``` # Usage +Import the `IgxDatePickerModule` in the module that you want to use it in: ```typescript -import { IgxDatePickerComponent } from "igniteui-angular"; +import { IgxDatePickerModule } from 'igniteui-angular'; + +@NgModule({ + imports: [IgxDatePickerModule] +}) +export class AppModule { } ``` Basic initialization ```html ``` -Custom formatter function with passed initial date and locale. -```html - - -``` -DatePicker with cancel and today buttons +This will produce an `igx-date-picker` without a default label. If you want to add a label you can import the `IgxLabelModule` and then in your `HTML` you can project it like so: ```html - - -``` - -The DatePicker's custom label can be set in two ways, either by changing the `label` property or in the way shown below. -````html - - - -You have also ability to disable the datePicker -```html - - -``` - -DatePicker with first day of week set to Monday and an event handler when selection is done. -```html - + ``` -The DatePicker also supports binding through `ngModel` if two-way date-bind is needed. +Custom formats for the input field. ```html - + ``` +If the `inputFormat` is not set, it will default to the format used by the browser. The `displayFormat` accepts all supported formats by Angular's `DatePipe`. -A date-picker opening a calendar than one month in the view and hiding the days that are outside of the current month -```html - - -``` -The DatePicker has `dropdown` mode as well. Custom display format and editor mask can be configured by setting the `format` and `mask` properties. +DatePicker with cancel and today buttons ```html - + ``` +If the these two properties are not set, the `igx-date-picker` will have any buttons. -The default DatePicker input group could be retemplated. +Additionally, custom buttons can be templated in the `igx-date-picker` using the `igxPickerActions` directive: ```html - - - - - - + + +
+ +
``` -In order to re-template a date picker in `dropdown` mode, you should pass the drop down target element to the `openDialog` method in order to position the drop down container accordingly: -```html - - - - - - - - -``` -The DatePicker action buttons could be retemplated. +The date picker also supports binding through `ngModel` if two-way date-bind is needed. It is also a custom validator which triggers ```html - - -
- -
-
+ + + + This field is required. + + + Value is not in range. + ``` -```typescript - public selectToday(picker: IgxDatePickerComponent) { - picker.calendar.value = picker.calendar.viewDate = new Date(Date.now()); - } -``` # API @@ -122,42 +94,51 @@ The DatePicker action buttons could be retemplated. | Name | Type | Description | |:----------|:-------------:|:------| | `id` | string | Unique identifier of the component. If not provided it will be automatically generated.| -| `todayBottonLabel` | `string` | Renders today button with custom name, which selects today date from calendar, and fill the datePicker input. | -| `cancelButtonLabel` | `string` | Renders cancel button with custom name, which closes the calendar. | -| `formatter` | `function` | Applied custom formatter on the selected or passed date. | -| `disabled` | `boolean` | Disable the datePicker. | -| `weekStart`| `Number \| WEEKDAYS` | Sets on which day will the week start. | +| `todayBottonLabel` | `string` | Renders today button with custom content, which selects today date from calendar, and fill the datePicker input. | +| `cancelButtonLabel` | `string` | Renders cancel button with custom content, which closes the calendar. | +| `formatter` | `function` | Applied custom formatter on the selected or passed in date. | +| `formatViews` | `PickersFormatViews` | Determines if `day`, `month` and `year` will be rendered in the calendar. `locale` and `calendarFormat` are taken into account as well, if present. +| `disabled` | `boolean` | Disables the date picker. | +| `weekStart`| `Number | WEEKDAYS` | Sets on which day will the week start. | | `locale` | `string` | Sets the locale used for formatting and displaying the dates in the calendar. For more information check out [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) page for valid formats. | -| `formatOptions` | `Object` | The format options passed along with the `locale` property used for formatting the dates. | -| `label` | `string` | Deprecated. Configure the input label text. | -| `labelVisibility` | `string` | Deprecated. Configure the input label text visibility. | -| `format` | `string` | Configure the date display format when in edit mode. Accepts formats using the d, M and y symbols, custom separators and the following pre-defined format options - shortDate, mediumDate, longDate and fullDate. | -| `mask` | `string` | Configure the date editor mask. Accepts the d, M and y symbols as mask - for example dd-MM-y. | +| `displayFormat` | `string` | The format used to display the picker's value when it's not being edited. | +| `inputFormat` | `string` | The editor's input mask. | | `disabledDates` | `DateRangeDescriptor[]` | Configure the disabled dates. | | `specialDates` | `DateRangeDescriptor[]` | Configure the special dates. | -| `value` | `Date` | Configure the datePicker value and selected date in the calendar. | -| `vertical` | `boolean` | Configure the calendar mode - horizontal or vertical in read-only datePicker. | -| `mode` | `InteractionMode` | Configure the datePicker mode - `dialog` or `dropdown`. In `dropdown` mode, the datePicker input is editable and drop down calendar is displayed, in a `dialog` mode - the input is read-only and calendar dialog appears to select a date.| -| `isSpinLoop` | `boolean` | Configure whether the date parts would spin continuously or stop when min/max value is reached in `dropdown` mode.| -| `monthViewsNumber` | `number` | Controls the number of month views displayed. | +| `calendarFormat` | `PickersFormatOptions` | The calendar's format options for the day view. +| `value` | `Date | string` | The date picker's value and the selected date in the calendar. | +| `headerOrientation` | `'horizontal' | 'vertical'` | Determines whether the calendar's header renders in vertical or horizontal state. Applies only in dialog mode. | +| `mode` | `'dropdown' | 'dialog'` | Sets whether `IgxDatePickerComponent` is in dialog or dropdown mode. | +| `spinLoop` | `boolean` | Determines if the currently spun date segment should loop over. | +| `spinDelta` | `DatePartDeltas` | Delta values used to increment or decrement each editor date part on spin actions. All values default to `1`. +| `type` | `IgxInputGroupType` | Determines how the picker will be styled. +| `displayMonthsCount` | `number` | Sets the number of displayed month views. Default is `2`. | | `hideOutsideDays`| `boolean` | Controls the visibility of the dates that do not belong to the current month. | +| `overlaySettings` | `OverlaySettings` | Changes the default overlay settings used by the `IgxDatePickerComponent`. +| `placeholder` | `string` | Sets the placeholder text for empty input. +| `minValue` | `Date | string` | The minimum value required for the picker to remain valid. +| `maxValue` | `Date | string` | The maximum value required for the editor to remain valid. + ### Outputs | Name | Return Type | Description | |:--:|:---|:---| -| `onSelection` | `Date` | Fired when selection is made in the calendar. The event contains the selected value(s) based on the type of selection the component is set to | -| `onOpened` | `datePicker` | Emitted when a datePicker calendar is opened. | -| `onClosed` | `datePicker` | Emitted when a datePicker calendar is closed. | -| `onClosing` | `CancelableBrowserEventArgs` | 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. | -| `valueChange` | `Date` | Fired when date picker value is changed | +| `opening` | `IBaseCancelableBrowserEventArgs` | Fired when the calendar has started opening, cancelable. | +| `opened` | `IBaseEventArgs` | Fired after the calendar has opened. | +| `closing` | `IBaseCancelableBrowserEventArgs` | Fired when the calendar has started closing, cancelable. | +| `closed` | `IBaseEventArgs` | Fired after the calendar has closed. | +| `validationFailed` | `IDatePickerValidationFailedEventArgs` | Emitted when a user enters an invalid date string or when the value is not within a min/max range. | +| `valueChange` | `Date` | Emitted when the picker's value changes. Allows two-way binding of `value`. | ### Methods | Name | Arguments | Return Type | Description | |:----------:|:------|:------|:------| -| `selectDate` | `date: Date` | `void` | Change the calendar selection. Calling this method will emit the `onSelection` event. | -| `deselectDate` | `void` | Deselects the calendar date and clear input field value. | -| `triggerTodaySelection` | `void` | Selects today's date in calendar and change the input field value. | -| `openDialog` | `target?: HTMLElement` | `void` | Opens the dialog or drop down, depending on the mode. | +| `select` | `Date` | `void` | Accepts a Date object and selects the corresponding date from the calendar. | +| `clear` | n/a | `void` | Clears the editor's date. | +| `selectToday` | n/a | `void` | Selects today's date in calendar and changes the input field value. | +| `open` | `OverlaySettings` | `void` | Opens the calendar. | +| `close` | n/a | `void` | Closes the calendar. | +| `toggle` | `OverlaySettings` | `void` | Toggles the calendar between opened and closed states. | +| `increment` | `DatePart?, number?` | | `void` | Accepts a `DatePart` and increments it by one. If no value is provided, it defaults to the part at the position of the cursor. +| `decrement` | `DatePart?, number?` | `void` | Accepts a `DatePart` and decrements it by one. If no value is provided, it defaults to the part at the position of the cursor. diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.common.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.common.ts index 7014d67dfd2..224312c2389 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.common.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.common.ts @@ -1,14 +1,4 @@ import { IBaseEventArgs } from '../core/utils'; -import { IgxDatePickerComponent } from './date-picker.component'; - -/** - * Provides information about date picker reference and its current value - * when onDisabledDate event is fired. - */ -export interface IDatePickerDisabledDateEventArgs extends IBaseEventArgs { - datePicker: IgxDatePickerComponent; - currentValue: Date; -} /** * Provides information about date picker reference and its previously valid value 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 ef728ceb4de..8d76f4d65a0 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 @@ -35,9 +35,7 @@ import { DatePart, DatePartDeltas, IgxDateTimeEditorDirective } from '../directi import { DeprecateProperty } from '../core/deprecateDecorators'; import { DateTimeUtil } from '../date-common/util/date-time.util'; import { PickerHeaderOrientation as PickerHeaderOrientation } from '../date-common/types'; -import { - IDatePickerDisabledDateEventArgs, IDatePickerValidationFailedEventArgs -} from './date-picker.common'; +import { IDatePickerValidationFailedEventArgs } from './date-picker.common'; import { IgxPickerToggleComponent, IgxPickerClearComponent, IgxPickerActionsDirective } from '../date-common/public_api'; let NEXT_ID = 0; @@ -374,19 +372,6 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr @Output() public valueChange = new EventEmitter(); - /** - * Emitted when the user types/spins to a disabled date in the date-picker editor. - * - * @example - * ```html - * - * ``` - */ - // eslint-disable-next-line @angular-eslint/no-output-on-prefix - @Output() - @DeprecateProperty('onDisabledDate has been deprecated.') - public onDisabledDate = new EventEmitter(); // TODO: remove event args as well - /** * Emitted when the user types/spins invalid date in the date-picker editor. * @@ -845,14 +830,6 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr } private subscribeToDateEditorEvents(): void { - this.dateTimeEditor.valueChange.pipe( - takeUntil(this._destroy$)).subscribe(newDate => { - this.value = newDate; - const dateValue = DateTimeUtil.isValidDate(newDate) ? newDate : DateTimeUtil.parseIsoDate(newDate); - if (newDate && this.disabledDates && !isDateInRanges(dateValue, this.disabledDates)) { - this.onDisabledDate.emit({ currentValue: this.dateValue, datePicker: this }); - } - }); this.dateTimeEditor.validationFailed.pipe( takeUntil(this._destroy$)).subscribe((event) => { this.validationFailed.emit({ diff --git a/projects/igniteui-angular/src/lib/date-range-picker/README.md b/projects/igniteui-angular/src/lib/date-range-picker/README.md index bf9221d7005..8a6faaf55e9 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/README.md +++ b/projects/igniteui-angular/src/lib/date-range-picker/README.md @@ -89,12 +89,12 @@ With projected inputs: `IgxDateRangePicker` with first day of the week set to `Monday` and handler when a range selection is made: ```html - + ``` `IgxDateRangePicker` that opens a calendar with more than `2` views and also hides days that are not part of each month: ```html - + ``` `IgxDateRangePicker` in a `drop-down` mode. @@ -109,23 +109,26 @@ With projected inputs: | Name | Type | Description | |:-----------------|:-------------------|:------------| | doneButtonText | string | Changes the default text of the `done` button. It will show up only in `dialog` mode. Default value is `Done`. | +| displayMonthsCount | number | Sets the number displayed month views. Default is `2`. | | formatter | function => string | Applies a custom formatter function on the selected or passed date. | | hideOutsideDays | boolean | Sets whether dates that are not part of the current month will be displayed. Default value is `false`. | | locale | string | Gets the `locale` of the calendar. Default value is `"en"`. | -| overlaySettings | OverlaySettings | Changes the default overlay settings used by the `IgxDateRangePickerComponent`. | | mode | InteractionMode | Sets whether `IgxDateRangePickerComponent` is in dialog or dropdown mode. Default is `dialog` | -| monthsViewNumber | number | Sets the number displayed month views. Default is `2`. | +| minValue | Date \| string | The minimum value in a valid range. | +| maxValue | Date \| string | The maximum value in a valid range. | +| outlet | IgxOverlayOutletDirective \| ElementRef | Gets/Sets the container used for the popup element. +| overlaySettings | OverlaySettings | Changes the default overlay settings used by the `IgxDateRangePickerComponent`. | | placeholder | string | Sets the `placeholder` for single-input `IgxDateRangePickerComponent`. | | weekStart | number | Sets the start day of the week. Can be assigned to a numeric value or to `WEEKDAYS` enum value. | ### Outputs | Name | Type | Description | |:-----------------|:----------------------|:------------| -| rangeSelected | IgxDateRangePickerComponent | Emitted when a full range was selected in the `IgxDateRangePickerComponent`. | -| onOpening | IBaseCancelableBrowserEventArgs | Emitted when the calendar starts opening, cancelable. | -| onOpened | IBaseEventArgs | Emitted when the `IgxDateRangePickerComponent` is opened. | -| onClosing | IBaseCancelableBrowserEventArgs | Emitted when the calendar starts closing, cancelable. | -| onClosed | IBaseEventArgs | Emitted when the `IgxDateRangePickerComponent` is closed. | +| valueChange | DateRange | Emitted when the picker's value changes. Used for two-way binding. | +| opening | IBaseCancelableBrowserEventArgs | Emitted when the calendar starts opening, cancelable. | +| opened | IBaseEventArgs | Emitted when the `IgxDateRangePickerComponent` is opened. | +| closing | IBaseCancelableBrowserEventArgs | Emitted when the calendar starts closing, cancelable. | +| closed | IBaseEventArgs | Emitted when the `IgxDateRangePickerComponent` is closed. | ### Methods | Name | Arguments | Return Type | Description | @@ -133,4 +136,4 @@ With projected inputs: | open | n/a | void | Opens the date picker's dropdown or dialog. | | close | n/a | void | Closes the date picker's dropdown or dialog. | | value | n/a | DateRange | Gets/sets the currently selected value / range from the calendar. | -| selectRange | startDate, endDate | void | Selects a range of dates, cancels previous selection. | +| select | startDate, endDate | void | Selects a range of dates, clears previous selection. | diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts index 20f17a9dfe2..844c2eb4187 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts @@ -234,17 +234,6 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective return this._maxValue; } - /** - * Enables/Disables the `IgxDateRangePickerComponent`. - * - * @example - * ```html - * - * ``` - */ - @Input() - public disabled = false; - /** * Sets the `placeholder` for single-input `IgxDateRangePickerComponent`. * diff --git a/projects/igniteui-angular/src/lib/time-picker/README.md b/projects/igniteui-angular/src/lib/time-picker/README.md index 674fc311ae6..d3d7f901418 100644 --- a/projects/igniteui-angular/src/lib/time-picker/README.md +++ b/projects/igniteui-angular/src/lib/time-picker/README.md @@ -1,6 +1,7 @@ # igx-time-picker Component -The **igx-time-picker** component allows you to select time which is presented into input field. +The **igx-time-picker** component allows you to select time from dropdown/dialog which is presented into input field. +A walk through of how to get started can be found [here](https://www.infragistics.com/products/ignite-ui-angular/angular/components/time_picker.html) # Usage ```typescript @@ -11,83 +12,47 @@ Basic initialization ```html ``` -Custom format with passed initial value. -```html - - -``` -You have also ability to disable the time picker +Custom formats for the input field. ```html - + ``` +If the `inputFormat` is not set, it will default to `hh:mm tt`. The `displayFormat` accepts all supported formats by Angular's `DatePipe`. -TimePicker with min and max values and onInvalidValueSelected event handler in order to decide what to do if an ivalid value is selected. +The time picker also supports binding through `ngModel` in case two-way date-binding is needed. ```html - + + + Time is not in range. + ``` -The TimePicker also supports binding through `ngModel` if two-way date-bind is needed. +Additionally the time picker spin options can be set by the `spinLoop` property. Its default value is `true`, in which case the spinning is wrapped around the min and max values. ```html - + ``` -The TimePicker also has to spin options. Spin loop and limited scroll modes are available. By default `isSpinLoop` is set to true. +In dialog mode the dialog's header orientation can be set to `vertical` or `horizontal` ```html - + ``` -The TimePicker has vertical and horizontal layout. By default the `vertical` is set to false -```html - - -``` -The TimePicker supports custom label. It can be set in the following way: +A label can be added to the time picker in the following way: ````html - + ```` -The TimePicker input group could be retemplated. -```html - - - - - - - - -``` -The TimePicker supports another interaction mode - an editable masked input and a dropdown. The user can enter or edit the time value inside the text input or select a vlaue from a dropdown, that will be applied on the text input. -```typescript -mode = InteractionMode.DropDown; -``` - -```html - - -``` - -In order to re-template the TimePicker in `dropdown` mode, you should pass the drop down target element to the `openDialog` method in order to position the drop down container accordingly: - -```html - - - - - - - - -``` - -The TimePicker action buttons could be retemplated. +The component's action buttons can be templated using the `igxPickerActions` directive: ```html @@ -109,47 +74,43 @@ The TimePicker action buttons could be retemplated. ###### Inputs | Name | Type | Description | |:----------|:-------------:|:------| -| `okButtonLabel` | string | Renders OK button with custom name, which commits the selected time, and fill the timePicker input. By default `okButtonLabel` is set to 'OK'. | -| `cancelButtonLabel` | string | Renders cancel button with custom name, which closes the dialog. By default `cancelButtonLabel` is set to 'Cancel'. | -| `value` | Date | Value of the timePicker. | +| `id` | string | Unique identifier of the component. If not provided it will be automatically generated.| +| `okButtonLabel` | string | Renders OK button with custom content, which closes the dropdown/dialog. By default `okButtonLabel` is set to 'OK'. | +| `cancelButtonLabel` | string | Renders cancel button with custom content, which closes the dropdown/dialog and reverts picker's value to the value at the moment of opening. By default `cancelButtonLabel` is set to 'Cancel'. | +| `value` | `Date | string` | Value of the time picker. | |`resourceStrings`| ITimePickerResourceStrings | Resource strings of the time-picker. | -| `disabled` | boolean | Disable the timePicker. | -| `itemsDelta`| object | Sets the delta for hour and minute items. By default `itemsDelta` is set ti {hours:1, minutes:1} | -| `minValue` | string | Sets minimum value. It should follow the `format` of the timePicker. | -| `maxValue` | string | Sets maximum value. It should follow the `format` of the timePicker. | -| `vertical` | boolean | Sets the orientation of the timePicker. By default `vertical` is set to true. | -| `format` | string | Gets/Sets format of time while timePicker has no focus. By default `format` is set to `hh:mm tt`. -List of time-flags: -"h": hours field in 12-hours format without leading zero -"hh": hours field in 12-hours format with leading zero -"H": hours field in 24-hours format without leading zero -"HH": hours field in 24-hours format with leading zero -"m": minutes field without leading zero -"mm": minutes field with leading zero -"s": seconds field without leading zero -"ss": seconds field with leading zero -"tt": 2 characters of string which represents AM/PM field | -| `isSpinLoop` | boolean | Determines the spin behavior. By default `isSpinLoop` is set to true. | -| `mode` | InteractionMode | Determines the interaction mode - a dialog picker or a dropdown with editable masked input. Default is dialog picker.| -| `promptChar` | string | Sets the character used to prompt the user for input. The default is a dash. Only applicable for dropdown mode. +| `disabled` | boolean | Disable the time picker. | +| `itemsDelta`| object | Sets the delta for hour, minute and second items. By default `itemsDelta` is set to {hour:1, minute:1, second:1} | +| `minValue` | `Date | string` | The minimum value required for the picker to remain valid. | +| `maxValue` | `Date | string` | The maximum value required for the editor to remain valid. | +| `headerOrientation` | `'horizontal' | 'vertical'` | Determines whether the dialog's header renders in vertical or horizontal state. Applies only in dialog mode. | +| `locale` | `string` | Sets the locale used for formatting and displaying time in the dropdown/dialog. For more information check out [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) page for valid formats. | +| `displayFormat` | `string` | The format used to display the picker's value when it's not being edited. | +| `inputFormat` | `string` | The editor's input mask. | +| `formatter` | `function` | Applied custom formatter on the selected or passed in date. | +| `spinLoop` | boolean | Determines the spin behavior. By default `spinLoop` is set to true. | +| `mode` | InteractionMode | Determines the interaction mode - a dialog picker or a dropdown with editable masked input. Default is dropdown picker.| +| `overlaySettings` | `OverlaySettings` | Changes the default overlay settings used by the `IgxTimePickerComponent`. +| `placeholder` | `string` | Sets the placeholder text for empty input. +| `type` | `IgxInputGroupType` | Determines how the picker will be styled. ### Outputs | Name | Description | |:--:|:---| -| `onValueChanged` | Fired when selection is made. The event contains the selected value. | -| `onInvalidValueSelected ` | Emitted when the user try to commit invalid value. The event contains the timePicker | -| `onOpened` | Emitted when a timePicker is being opened. | -| `onClosed` | Emitted when a timePicker is being closed. | +| `opening` | `IBaseCancelableBrowserEventArgs` | Fired when the dropdown/dialog has started opening, cancelable. | +| `opened` | `IBaseEventArgs` | Fired after the dropdown/dialog has opened. | +| `closing` | `IBaseCancelableBrowserEventArgs` | Fired when the dropdown/dialog has started closing, cancelable. | +| `closed` | `IBaseEventArgs` | Fired after the dropdown/dialog has closed. | +| `validationFailed` | `ITimePickerValidationFailedEventArgs` | Emitted when an invalid time string is entered or when the value is outside the min/max range. | +| `valueChange` | `Date | string` | Emitted when the picker's value changes. Allows two-way binding of `value`. | ### Methods | Name | Arguments | Return Type | Description | |:----------:|:------|:------|:------| -| `okButtonClick` | | `void` | If current value is valid selects it and closes the dialog. | -| `cancelButtonClick` | | `void` | Closes the dialog without selecting the current value. | -| `hoursInView` | | `string[]` | Returns an array of the hours currently in view. | -| `minutesInView` | | `string[]` | Returns an array of the minutes currently in view. | -| `ampmInView` | | `string[]` | Returns an array of the ampm currently in view. | -| `scrollHourIntoView` | `(item: string)` | `void` | Scrolls a hour item into view. | -| `scrollMinuteIntoView` | `(item: string)` | `void` | Scrolls a minute item into view. | -| `scrollAmPmIntoView` | `(item: string)` | `void` | Scrolls a period item into view. | -| `openDialog` | `target?: HTMLElement` | `void` | Opens the dialog or drop down, depending on the mode. | +| `select` | `Date | string` | `void` | Accepts a Date object or string and selects the corresponding time from the dropdown/dialog. | +| `clear` | n/a | `void` | Clears the picker's value in case it is a string and resets it to `00:00:00` when it is a Date object | +| `open` | `OverlaySettings` | `void` | Opens the dropdown/dialog. | +| `close` | n/a | `void` | Closes the dropdown/dialog. | +| `toggle` | `OverlaySettings` | `void` | Toggles the dropdown/dialog between opened and closed states. | +| `increment` | `DatePart?, number?` | | `void` | Accepts a `DatePart` and increments it by one. If no value is provided, it defaults to the part at the position of the cursor. +| `decrement` | `DatePart?, number?` | `void` | Accepts a `DatePart` and decrements it by one. If no value is provided, it defaults to the part at the position of the cursor.