Skip to content

Commit efcaf6d

Browse files
committed
feat(pickers): custom buttons functionality #4647
1 parent 0c2d73c commit efcaf6d

17 files changed

+401
-25
lines changed

projects/igniteui-angular/migrations/migration-collection.json

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
"version": "7.2.0",
4141
"description": "Updates Ignite UI for Angular from v7.0.2 to v7.2.0",
4242
"factory": "./update-7_2_0"
43+
},
44+
"migration-09": {
45+
"version": "7.3.3",
46+
"description": "Updates Ignite UI for Angular from v7.2.0 to v7.3.3",
47+
"factory": "./update-7_3_3"
4348
}
4449
}
4550
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"$schema": "../../common/schema/binding.schema.json",
3+
"changes": [
4+
{
5+
"name": "onOpen",
6+
"replaceWith": "onOpened",
7+
"owner": {
8+
"selector": "igx-time-picker",
9+
"type": "component"
10+
}
11+
},
12+
{
13+
"name": "onClose",
14+
"replaceWith": "onClosed",
15+
"owner": {
16+
"selector": "igx-time-picker",
17+
"type": "component"
18+
}
19+
},
20+
{
21+
"name": "onOpen",
22+
"replaceWith": "onOpened",
23+
"owner": {
24+
"selector": "igx-date-picker",
25+
"type": "component"
26+
}
27+
},
28+
{
29+
"name": "onClose",
30+
"replaceWith": "onClosed",
31+
"owner": {
32+
"selector": "igx-date-picker",
33+
"type": "component"
34+
}
35+
}
36+
]
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import * as path from 'path';
2+
3+
// tslint:disable:no-implicit-dependencies
4+
import { virtualFs } from '@angular-devkit/core';
5+
import { EmptyTree } from '@angular-devkit/schematics';
6+
// tslint:disable-next-line:no-submodule-imports
7+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
8+
9+
describe('Update 7.3.3', () => {
10+
let appTree: UnitTestTree;
11+
const schematicRunner = new SchematicTestRunner('ig-migrate', path.join(__dirname, '../migration-collection.json'));
12+
const configJson = {
13+
defaultProject: 'testProj',
14+
projects: {
15+
testProj: {
16+
sourceRoot: '/testSrc'
17+
}
18+
},
19+
schematics: {
20+
'@schematics/angular:component': {
21+
prefix: 'appPrefix'
22+
}
23+
}
24+
};
25+
26+
beforeEach(() => {
27+
appTree = new UnitTestTree(new EmptyTree());
28+
appTree.create('/angular.json', JSON.stringify(configJson));
29+
});
30+
31+
it('should update time picker events', done => {
32+
appTree.create(
33+
'/testSrc/appPrefix/component/test.component.html',
34+
`<igx-time-picker (onOpen)="handler" (onClose)="handler"></igx-time-picker>`
35+
);
36+
const tree = schematicRunner.runSchematic('migration-09', {}, appTree);
37+
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html'))
38+
.toEqual(
39+
`<igx-time-picker (onOpened)="handler" (onClosed)="handler"></igx-time-picker>`);
40+
done();
41+
});
42+
43+
it('should update date picker events', done => {
44+
appTree.create(
45+
'/testSrc/appPrefix/component/test.component.html',
46+
`<igx-date-picker (onOpen)="handler" (onClose)="handler"></igx-date-picker>`
47+
);
48+
const tree = schematicRunner.runSchematic('migration-09', {}, appTree);
49+
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html'))
50+
.toEqual(
51+
`<igx-date-picker (onOpened)="handler" (onClosed)="handler"></igx-date-picker>`);
52+
done();
53+
});
54+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as path from 'path';
2+
3+
// tslint:disable:no-implicit-dependencies
4+
import { normalize } from '@angular-devkit/core';
5+
import {
6+
chain,
7+
Rule,
8+
SchematicContext,
9+
SchematicsException,
10+
Tree
11+
} from '@angular-devkit/schematics';
12+
import { filterSourceDirs } from '../common/filterSourceDirs';
13+
import { getImportModulePositions } from '../common/tsUtils';
14+
import { UpdateChanges } from '../common/UpdateChanges';
15+
16+
const version = '7.3.3';
17+
18+
export default function(): Rule {
19+
return (host: Tree, context: SchematicContext) => {
20+
context.logger.info(`Applying migration for Ignite UI for Angular to version ${version}`);
21+
22+
const update = new UpdateChanges(__dirname, host, context);
23+
update.applyChanges();
24+
};
25+
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
<igx-calendar #calendar></igx-calendar>
2-
<div class="igx-date-picker__buttons" *ngIf="isReadonly &&
3-
(cancelButtonLabel || todayButtonLabel)">
1+
<ng-template #defaultDatePickerActions>
42
<button #closeButton *ngIf="cancelButtonLabel" igxButton="flat" igxRipple (click)="closeCalendar()">
53
{{ cancelButtonLabel }}
64
</button>
75
<button #todayButton *ngIf="todayButtonLabel" igxButton="flat" igxRipple (click)="triggerTodaySelection()">
86
{{ todayButtonLabel }}
97
</button>
8+
</ng-template>
9+
<div>
10+
<igx-calendar #calendar></igx-calendar>
11+
<div class="igx-date-picker__buttons">
12+
<ng-container *ngTemplateOutlet="datePickerActions ? datePickerActions.template : defaultDatePickerActions"></ng-container>
13+
</div>
1014
</div>

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

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Component, ViewChild, Input, Output, EventEmitter, HostListener, HostBinding } from '@angular/core';
22
import { IgxCalendarComponent } from '../calendar';
33
import { InteractionMode } from '../core/enums';
4+
import { IgxDatePickerActionsDirective } from './date-picker.directives';
45

56
/**
67
* @hidden
@@ -26,6 +27,9 @@ export class IgxCalendarContainerComponent {
2627
@Input()
2728
public todayButtonLabel: string;
2829

30+
@Input()
31+
public datePickerActions: IgxDatePickerActionsDirective;
32+
2933
@Output()
3034
public onClose = new EventEmitter();
3135

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

+11
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ describe('IgxDatePicker', () => {
277277
const picker = document.getElementsByClassName('igx-calendar-picker');
278278
const formattedSubHeaderText = (picker[0].children[1] as HTMLElement).innerText;
279279
expect(formattedSubHeaderText).toBe('2019/Oct');
280+
281+
const buttons = document.getElementsByClassName('igx-button--flat');
282+
expect(buttons.length).toEqual(1);
283+
expect((buttons[0]as HTMLElement).innerText).toBe('TEST');
280284
});
281285

282286
it('Retemplated calendar in date picker - dropdown mode', () => {
@@ -295,6 +299,10 @@ describe('IgxDatePicker', () => {
295299
const picker = document.getElementsByClassName('igx-calendar-picker');
296300
const formattedSubHeaderText = (picker[0].children[1] as HTMLElement).innerText;
297301
expect(formattedSubHeaderText).toBe('2019/Oct');
302+
303+
const buttons = document.getElementsByClassName('igx-button--flat');
304+
expect(buttons.length).toEqual(1);
305+
expect((buttons[0]as HTMLElement).innerText).toBe('TEST');
298306
});
299307

300308
it('locale propagate calendar value (de-DE)', () => {
@@ -1197,6 +1205,9 @@ export class IgxDatePickerEditableComponent {
11971205
<span class="date__el" (click)="format.yearView()">{{ format.year.combined }}/</span>
11981206
<span class="date__el" (click)="format.monthView()">{{ format.month.combined | titlecase }}</span>
11991207
</ng-template>
1208+
<ng-template igxDatePickerActions>
1209+
<button igxButton="flat">TEST</button>
1210+
</ng-template>
12001211
</igx-date-picker>
12011212
`
12021213
})

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

+45-4
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ import {
5050
} from './date-picker.utils';
5151
import { DatePickerDisplayValuePipe, DatePickerInputValuePipe } from './date-picker.pipes';
5252
import { IDatePicker } from './date-picker.common';
53-
import { KEYS } from '../core/utils';
54-
import { IgxDatePickerTemplateDirective } from './date-picker.directives';
53+
import { KEYS, CancelableBrowserEventArgs } from '../core/utils';
54+
import { IgxDatePickerTemplateDirective, IgxDatePickerActionsDirective } from './date-picker.directives';
5555
import { IgxCalendarContainerComponent } from './calendar-container.component';
5656
import { InteractionMode } from '../core/enums';
5757
import { getViewportRect } from '../services/overlay/utilities';
5858
import { fadeIn, fadeOut } from '../animations/fade';
59+
import { DeprecateProperty } from '../core/deprecateDecorators';
5960

6061
let NEXT_ID = 0;
6162

@@ -549,9 +550,16 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
549550
*<igx-date-picker (onOpen)="open($event)" cancelButtonLabel="cancel" todayButtonLabel="today"></igx-date-picker>
550551
*```
551552
*/
553+
@DeprecateProperty(`'onOpen' @Ouput property is deprecated\nUse 'onOpened' instead.`)
552554
@Output()
553555
public onOpen = new EventEmitter<IgxDatePickerComponent>();
554556

557+
/**
558+
*An event that is emitted when the `IgxDatePickerComponent` calendar is opened.
559+
*/
560+
@Output()
561+
public onOpened = new EventEmitter<IgxDatePickerComponent>();
562+
555563
/**
556564
*"An event that is emitted when the `IgxDatePickerComponent` is closed.
557565
*```typescript
@@ -563,8 +571,22 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
563571
*<igx-date-picker (onClose)="close($event)" cancelButtonLabel="cancel" todayButtonLabel="today"></igx-date-picker>
564572
*```
565573
*/
574+
@DeprecateProperty(`'onClose' @Ouput property is deprecated\nUse 'onClosed' instead.`)
566575
@Output()
567576
public onClose = new EventEmitter<IgxDatePickerComponent>();
577+
578+
/**
579+
*An event that is emitted when the `IgxDatePickerComponent` is closed.
580+
*/
581+
@Output()
582+
public onClosed = new EventEmitter<IgxDatePickerComponent>();
583+
584+
/**
585+
* An event that is emitted when the `IgxDatePickerComponent` is being closed.
586+
*/
587+
@Output()
588+
public onClosing = new EventEmitter<CancelableBrowserEventArgs>();
589+
568590
/**
569591
*An @Output property that is fired when selection is made in the calendar.
570592
*```typescript
@@ -673,6 +695,12 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
673695
@ContentChild(IgxCalendarSubheaderTemplateDirective, { read: IgxCalendarSubheaderTemplateDirective })
674696
public subheaderTemplate: IgxCalendarSubheaderTemplateDirective;
675697

698+
/**
699+
*@hidden
700+
*/
701+
@ContentChild(IgxDatePickerActionsDirective, { read: IgxDatePickerActionsDirective })
702+
public datePickerActionsDirective: IgxDatePickerActionsDirective;
703+
676704
public calendar: IgxCalendarComponent;
677705
public hasHeader = true;
678706
public collapsed = true;
@@ -804,6 +832,12 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
804832
this._onClosed();
805833
});
806834

835+
this._overlayService.onClosing.pipe(
836+
filter(overlay => overlay.id === this._componentID),
837+
takeUntil(this._destroy$)).subscribe((event) => {
838+
this.onClosing.emit(event);
839+
});
840+
807841
if (this.mode === InteractionMode.DropDown) {
808842
this.dateFormatParts = DatePickerUtil.parseDateFormat(this.mask, this.locale);
809843
if (this.mask === undefined) {
@@ -1159,6 +1193,9 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
11591193

11601194
private _onOpened(event): void {
11611195
this._onTouchedCallback();
1196+
this.onOpened.emit(this);
1197+
1198+
// TODO: remove this line after deprecating 'onOpen'
11621199
this.onOpen.emit(this);
11631200

11641201
if (this.calendar) {
@@ -1169,6 +1206,9 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
11691206
private _onClosed(): void {
11701207
this.collapsed = true;
11711208
this._componentID = null;
1209+
this.onClosed.emit(this);
1210+
1211+
// TODO: remove this line after deprecating 'onClose'
11721212
this.onClose.emit(this);
11731213

11741214
if (this.getEditElement()) {
@@ -1200,6 +1240,7 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
12001240
componentInstance.vertical = isVertical;
12011241
componentInstance.cancelButtonLabel = this.cancelButtonLabel;
12021242
componentInstance.todayButtonLabel = this.todayButtonLabel;
1243+
componentInstance.datePickerActions = this.datePickerActionsDirective;
12031244

12041245
componentInstance.onClose.pipe(takeUntil(this._destroy$)).subscribe(() => this.closeCalendar());
12051246
componentInstance.onTodaySelection.pipe(takeUntil(this._destroy$)).subscribe(() => this.triggerTodaySelection());
@@ -1265,9 +1306,9 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
12651306
* @hidden
12661307
*/
12671308
@NgModule({
1268-
declarations: [IgxDatePickerComponent, IgxCalendarContainerComponent,
1309+
declarations: [IgxDatePickerComponent, IgxCalendarContainerComponent, IgxDatePickerActionsDirective,
12691310
IgxDatePickerTemplateDirective, DatePickerDisplayValuePipe, DatePickerInputValuePipe],
1270-
exports: [IgxDatePickerComponent, IgxDatePickerTemplateDirective, DatePickerDisplayValuePipe, DatePickerInputValuePipe],
1311+
exports: [IgxDatePickerComponent, IgxDatePickerTemplateDirective, IgxDatePickerActionsDirective, DatePickerDisplayValuePipe, DatePickerInputValuePipe],
12711312
imports: [CommonModule, IgxIconModule, IgxInputGroupModule, IgxCalendarModule, IgxButtonModule, IgxRippleModule, IgxMaskModule],
12721313
entryComponents: [IgxCalendarContainerComponent]
12731314
})

projects/igniteui-angular/src/lib/date-picker/date-picker.directives.ts

+10
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,13 @@ import { Directive, TemplateRef } from '@angular/core';
1212
export class IgxDatePickerTemplateDirective {
1313
constructor(public template: TemplateRef<any>) { }
1414
}
15+
16+
/**
17+
* IgxDatePickerActionsDirective can be used to re-template the dropdown/dialog action buttons.
18+
*/
19+
@Directive({
20+
selector: '[igxDatePickerActions]'
21+
})
22+
export class IgxDatePickerActionsDirective {
23+
constructor(public template: TemplateRef<any>) { }
24+
}

projects/igniteui-angular/src/lib/time-picker/time-picker.component.html

+6-3
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ <h2 class="igx-time-picker__header-hour">
4444
<span [igxAmPmItem]="ampm" *ngFor="let ampm of ampmView">{{ ampm }}</span>
4545
</div>
4646
</div>
47-
<div *ngIf="mode === 'dialog'" class="igx-time-picker__buttons">
48-
<button *ngIf="cancelButtonLabel.length" igxButton="flat" (click)="cancelButtonClick()">
47+
<div *ngIf="!timePickerActionsDirective && (cancelButtonLabel || okButtonLabel)" class="igx-time-picker__buttons">
48+
<button *ngIf="cancelButtonLabel" igxButton="flat" (click)="cancelButtonClick()">
4949
{{cancelButtonLabel}}
5050
</button>
51-
<button *ngIf="okButtonLabel.length" igxButton="flat" (click)="okButtonClick()">
51+
<button *ngIf="okButtonLabel" igxButton="flat" (click)="okButtonClick()">
5252
{{okButtonLabel}}
5353
</button>
5454
</div>
55+
<ng-container *ngIf="timePickerActionsDirective">
56+
<ng-content select="igx-time-picker-actions,[igxTimePickerActions]"></ng-content>
57+
</ng-container>
5558
</div>
5659
</div>

0 commit comments

Comments
 (0)