Skip to content

Commit 5dfd22f

Browse files
SAndreevabkulov
authored andcommitted
Time picker: add hour/minute only mode - master (#5023)
* feat(time picker): add hour/minute mode #4679 * chore(*): fix lint errors #4679 * chore(*): bug fixing/improvements #4679 * chore(*): fix lint error #4679 * chore(*): address some review comments #4679 * chore(*): Address more review comments #4679 * chore(*): fix build error #4679
1 parent 763dea9 commit 5dfd22f

9 files changed

+474
-87
lines changed

Diff for: projects/igniteui-angular/src/lib/directives/mask/mask.directive.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,14 @@ export class IgxMaskDirective implements OnInit, ControlValueAccessor {
6060
* @memberof IgxMaskDirective
6161
*/
6262
@Input()
63-
public placeholder: string;
63+
public set placeholder(val: string) {
64+
this._placeholder = val;
65+
this.nativeElement.setAttribute('placeholder', this._placeholder);
66+
}
67+
68+
public get placeholder(): string {
69+
return this._placeholder;
70+
}
6471

6572
/**
6673
* Specifies a pipe to be used on blur.
@@ -148,6 +155,11 @@ export class IgxMaskDirective implements OnInit, ControlValueAccessor {
148155
*/
149156
private _selection: number;
150157

158+
/**
159+
*@hidden
160+
*/
161+
private _placeholder: string;
162+
151163
/**
152164
*@hidden
153165
*/

Diff for: projects/igniteui-angular/src/lib/time-picker/time-picker.common.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export const IGX_TIME_PICKER_COMPONENT = 'IgxTimePickerComponentToken';
66

77
/** @hidden */
88
export interface IgxTimePickerBase {
9-
_ampmItems: any[];
109
hourList: ElementRef;
1110
minuteList: ElementRef;
1211
ampmList: ElementRef;
@@ -17,6 +16,9 @@ export interface IgxTimePickerBase {
1716
promptChar: string;
1817
cleared: boolean;
1918
mode: InteractionMode;
19+
showHoursList: boolean;
20+
showMinutesList: boolean;
21+
showAmPmList: boolean;
2022
nextHour();
2123
prevHour();
2224
nextMinute();

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ <h2 class="igx-time-picker__header-hour">
4444
</div>
4545
<div class="igx-time-picker__main">
4646
<div class="igx-time-picker__body">
47-
<div #hourList [igxItemList]="'hourList'">
47+
<div *ngIf="showHoursList" #hourList [igxItemList]="'hourList'">
4848
<span [igxHourItem]="hour" *ngFor="let hour of hourView">{{ hour }}</span>
4949
</div>
50-
<div #minuteList [igxItemList]="'minuteList'">
50+
<div *ngIf="showMinutesList" #minuteList [igxItemList]="'minuteList'">
5151
<span [igxMinuteItem]="minute" *ngFor="let minute of minuteView">{{ minute }}</span>
5252
</div>
53-
<div #ampmList [igxItemList]="'ampmList'">
53+
<div *ngIf="showAmPmList" #ampmList [igxItemList]="'ampmList'">
5454
<span [igxAmPmItem]="ampm" *ngFor="let ampm of ampmView">{{ ampm }}</span>
5555
</div>
5656
</div>

Diff for: projects/igniteui-angular/src/lib/time-picker/time-picker.component.spec.ts

+239-2
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ describe('IgxTimePicker', () => {
616616
const selectHour = hourColumn.children[3];
617617
const AMPMColumn: any = dom.query(By.css('.igx-time-picker__ampmList'));
618618

619-
expect(AMPMColumn.children.length).toBe(0);
619+
expect(AMPMColumn).toBeNull();
620620
expect(selectHour.nativeElement.innerText).toBe('00');
621621
}));
622622

@@ -1537,6 +1537,242 @@ describe('IgxTimePicker', () => {
15371537
expect(input.nativeElement.value).toEqual('10:45 AM');
15381538
}));
15391539
});
1540+
1541+
describe('Hour/minute only mode', () => {
1542+
configureTestSuite();
1543+
let fixture, timePicker, dom, input;
1544+
1545+
beforeEach(
1546+
async(() => {
1547+
fixture = TestBed.createComponent(IgxTimePickerDropDownSingleHourComponent);
1548+
fixture.detectChanges();
1549+
1550+
timePicker = fixture.componentInstance.timePicker;
1551+
dom = fixture.debugElement;
1552+
input = dom.query(By.directive(IgxInputDirective));
1553+
})
1554+
);
1555+
1556+
afterEach(async(() => {
1557+
UIInteractions.clearOverlay();
1558+
}));
1559+
1560+
it('Should render dropdown and input group correctly when format conatains only hours.', fakeAsync(() => {
1561+
fixture.componentInstance.format = 'hh tt';
1562+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1563+
fixture.detectChanges();
1564+
1565+
const iconTime = dom.queryAll(By.css('.igx-icon'))[0];
1566+
1567+
UIInteractions.clickElement(iconTime);
1568+
tick();
1569+
fixture.detectChanges();
1570+
1571+
const hourColumn = dom.query(By.css('.igx-time-picker__hourList'));
1572+
const minuteColumn = dom.query(By.css('.igx-time-picker__minuteList'));
1573+
const ampmColumn = dom.query(By.css('.igx-time-picker__ampmList'));
1574+
1575+
expect(hourColumn).not.toBeNull();
1576+
expect(ampmColumn).not.toBeNull();
1577+
expect(minuteColumn).toBeNull();
1578+
}));
1579+
1580+
it('Should mask editable input correctly when format conatains only hours.', fakeAsync(() => {
1581+
fixture.componentInstance.format = 'hh tt';
1582+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1583+
fixture.detectChanges();
1584+
1585+
const clearTime = dom.queryAll(By.css('.igx-icon'))[1];
1586+
1587+
UIInteractions.clickElement(clearTime);
1588+
fixture.detectChanges();
1589+
input.nativeElement.dispatchEvent(new Event('focus'));
1590+
fixture.detectChanges();
1591+
1592+
input.nativeElement.dispatchEvent(new Event('blur'));
1593+
fixture.detectChanges();
1594+
1595+
expect(input.nativeElement.value).toEqual('');
1596+
expect(input.nativeElement.placeholder).toEqual('hh tt');
1597+
1598+
input.nativeElement.dispatchEvent(new Event('focus'));
1599+
fixture.detectChanges();
1600+
1601+
expect(input.nativeElement.value).toBe('-- AM');
1602+
}));
1603+
1604+
it('Should navigate dropdown lists correctly when format conatains only hours.', fakeAsync(() => {
1605+
fixture.componentInstance.format = 'hh tt';
1606+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1607+
fixture.detectChanges();
1608+
1609+
const iconTime = dom.queryAll(By.css('.igx-icon'))[0];
1610+
1611+
UIInteractions.clickElement(iconTime);
1612+
tick();
1613+
fixture.detectChanges();
1614+
1615+
dom.query(By.css('.igx-time-picker__hourList')).nativeElement.focus();
1616+
fixture.detectChanges();
1617+
1618+
expect(document.activeElement.classList).toContain('igx-time-picker__hourList');
1619+
1620+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
1621+
fixture.detectChanges();
1622+
1623+
expect(document.activeElement.classList).toContain('igx-time-picker__ampmList');
1624+
1625+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
1626+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true }));
1627+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
1628+
tick();
1629+
fixture.detectChanges();
1630+
1631+
expect(input.nativeElement.value).toEqual('04 PM');
1632+
expect(timePicker.value).toEqual(new Date(2018, 10, 27, 16, 45, 0, 0));
1633+
}));
1634+
1635+
it('Should navigate dropdown lists correctly when format conatains only minutes.', fakeAsync(() => {
1636+
fixture.componentInstance.format = 'mm tt';
1637+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1638+
fixture.detectChanges();
1639+
1640+
const iconTime = dom.queryAll(By.css('.igx-icon'))[0];
1641+
1642+
UIInteractions.clickElement(iconTime);
1643+
tick();
1644+
fixture.detectChanges();
1645+
1646+
dom.query(By.css('.igx-time-picker__minuteList')).nativeElement.focus();
1647+
fixture.detectChanges();
1648+
1649+
expect(document.activeElement.classList).toContain('igx-time-picker__minuteList');
1650+
1651+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
1652+
fixture.detectChanges();
1653+
1654+
expect(document.activeElement.classList).toContain('igx-time-picker__ampmList');
1655+
1656+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
1657+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
1658+
document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
1659+
tick();
1660+
fixture.detectChanges();
1661+
1662+
expect(input.nativeElement.value).toEqual('46 PM');
1663+
expect(timePicker.value).toEqual(new Date(2018, 10, 27, 17, 46, 0, 0));
1664+
}));
1665+
1666+
it('Should spin editable input correctly when format conatains only hours - 24 hour format.', fakeAsync(() => {
1667+
fixture.componentInstance.format = 'HH';
1668+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1669+
fixture.detectChanges();
1670+
1671+
expect(input.nativeElement.value).toBe('17');
1672+
1673+
input.nativeElement.focus();
1674+
input.nativeElement.setSelectionRange(0, 0);
1675+
fixture.detectChanges();
1676+
1677+
UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', input.nativeElement, true);
1678+
fixture.detectChanges();
1679+
1680+
expect(input.nativeElement.value).toBe('18');
1681+
expect(timePicker.value).toEqual(new Date(2018, 10, 27, 18, 45, 0, 0));
1682+
}));
1683+
1684+
it('Should spin editable input correctly when format conatains only minutes.', fakeAsync(() => {
1685+
fixture.componentInstance.format = 'mm tt';
1686+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1687+
fixture.detectChanges();
1688+
1689+
expect(input.nativeElement.value).toBe('45 PM');
1690+
1691+
input.nativeElement.setSelectionRange(0, 0);
1692+
tick();
1693+
fixture.detectChanges();
1694+
1695+
UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', input.nativeElement, true);
1696+
fixture.detectChanges();
1697+
1698+
expect(input.nativeElement.value).toBe('46 PM');
1699+
expect(timePicker.value).toEqual(new Date(2018, 10, 27, 17, 46, 0, 0));
1700+
}));
1701+
1702+
it('Should spin editable input AM/PM correctly when format conatains only hours.', fakeAsync(() => {
1703+
fixture.componentInstance.format = 'hh tt';
1704+
fixture.componentInstance.customDate = new Date(2018, 10, 27, 17, 45, 0, 0);
1705+
fixture.detectChanges();
1706+
1707+
expect(input.nativeElement.value).toBe('05 PM');
1708+
1709+
input.nativeElement.setSelectionRange(3, 3);
1710+
fixture.detectChanges();
1711+
1712+
UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', input.nativeElement, true);
1713+
fixture.detectChanges();
1714+
1715+
expect(input.nativeElement.value).toBe('05 AM');
1716+
expect(timePicker.value).toEqual(new Date(2018, 10, 27, 5, 45, 0, 0));
1717+
}));
1718+
1719+
it('Should render dialog and input group correctly when format conatains only minutes.', fakeAsync(() => {
1720+
fixture.componentInstance.format = 'mm';
1721+
fixture.componentInstance.mode = InteractionMode.Dialog;
1722+
fixture.detectChanges();
1723+
1724+
input = dom.query(By.directive(IgxInputDirective));
1725+
UIInteractions.clickElement(input);
1726+
fixture.detectChanges();
1727+
1728+
const hourColumn = dom.query(By.css('.igx-time-picker__hourList'));
1729+
const minuteColumn = dom.query(By.css('.igx-time-picker__minuteList'));
1730+
const ampmColumn = dom.query(By.css('.igx-time-picker__ampmList'));
1731+
1732+
expect(hourColumn).toBeNull();
1733+
expect(ampmColumn).toBeNull();
1734+
expect(minuteColumn).not.toBeNull();
1735+
1736+
expect(input.nativeElement.value).toEqual('05');
1737+
expect(timePicker.mask).toEqual('00');
1738+
expect(timePicker.value).toEqual(fixture.componentInstance.customDate);
1739+
1740+
const headerHour = dom.query(By.css('.igx-time-picker__header-hour'));
1741+
const headerAmPm = dom.query(By.css('.igx-time-picker__header-ampm'));
1742+
1743+
expect(headerHour.nativeElement.innerText.replace(/\n/g, '')).toEqual('4:05');
1744+
expect(headerAmPm.nativeElement.innerText).toEqual('');
1745+
}));
1746+
1747+
it('Should render dialog and input group correctly when format conatains only hours.', fakeAsync(() => {
1748+
fixture.componentInstance.format = 'hh tt';
1749+
fixture.componentInstance.mode = InteractionMode.Dialog;
1750+
fixture.detectChanges();
1751+
1752+
input = dom.query(By.directive(IgxInputDirective));
1753+
UIInteractions.clickElement(input);
1754+
tick();
1755+
fixture.detectChanges();
1756+
1757+
const hourColumn = dom.query(By.css('.igx-time-picker__hourList'));
1758+
const minuteColumn = dom.query(By.css('.igx-time-picker__minuteList'));
1759+
const ampmColumn = dom.query(By.css('.igx-time-picker__ampmList'));
1760+
1761+
expect(hourColumn).not.toBeNull();
1762+
expect(ampmColumn).not.toBeNull();
1763+
expect(minuteColumn).toBeNull();
1764+
1765+
expect(input.nativeElement.value).toEqual('04 AM');
1766+
expect(timePicker.mask).toEqual('00 LL');
1767+
expect(timePicker.value).toEqual(fixture.componentInstance.customDate);
1768+
1769+
const headerHour = dom.query(By.css('.igx-time-picker__header-hour'));
1770+
const headerAmPm = dom.query(By.css('.igx-time-picker__header-ampm'));
1771+
1772+
expect(headerHour.nativeElement.innerText.replace(/\n/g, '')).toEqual('04:5');
1773+
expect(headerAmPm.nativeElement.innerText).toEqual('AM');
1774+
}));
1775+
});
15401776
});
15411777

15421778
@Component({
@@ -1670,13 +1906,14 @@ export class IgxTimePickerDropDownComponent {
16701906
<igx-time-picker
16711907
[value]="customDate"
16721908
[mode]="mode"
1673-
[format]="'H:m'">
1909+
[format]="format">
16741910
</igx-time-picker>
16751911
`
16761912
})
16771913
export class IgxTimePickerDropDownSingleHourComponent {
16781914
customDate = new Date(2018, 10, 27, 4, 5);
16791915
mode = InteractionMode.DropDown;
1916+
format = 'H:m';
16801917

16811918
@ViewChild(IgxTimePickerComponent) public timePicker: IgxTimePickerComponent;
16821919
}

0 commit comments

Comments
 (0)