diff --git a/e2e-app/src/app/app.module.ts b/e2e-app/src/app/app.module.ts
index 2b08dcc290..5a89e1888b 100644
--- a/e2e-app/src/app/app.module.ts
+++ b/e2e-app/src/app/app.module.ts
@@ -23,6 +23,7 @@ import {TooltipFocusComponent} from './tooltip/focus/tooltip-focus.component';
import {TooltipPositionComponent} from './tooltip/position/tooltip-position.component';
import {TypeaheadAutoCloseComponent} from './typeahead/autoclose/typeahead-autoclose.component';
import {TypeaheadFocusComponent} from './typeahead/focus/typeahead-focus.component';
+import {TimepickerFilterComponent} from './timepicker/filter/timepicker-filter.component';
import {TimepickerNavigationComponent} from './timepicker/navigation/timepicker-navigation.component';
import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-validation.component';
@@ -47,6 +48,7 @@ import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-val
TypeaheadFocusComponent,
TypeaheadValidationComponent,
TypeaheadAutoCloseComponent,
+ TimepickerFilterComponent,
TimepickerNavigationComponent,
],
imports: [BrowserModule, FormsModule, ReactiveFormsModule, routing, NgbModule],
diff --git a/e2e-app/src/app/app.routing.ts b/e2e-app/src/app/app.routing.ts
index 4a2f46f47d..7308166d4f 100644
--- a/e2e-app/src/app/app.routing.ts
+++ b/e2e-app/src/app/app.routing.ts
@@ -15,6 +15,7 @@ import {TooltipFocusComponent} from './tooltip/focus/tooltip-focus.component';
import {TooltipPositionComponent} from './tooltip/position/tooltip-position.component';
import {TypeaheadAutoCloseComponent} from './typeahead/autoclose/typeahead-autoclose.component';
import {TypeaheadFocusComponent} from './typeahead/focus/typeahead-focus.component';
+import {TimepickerFilterComponent} from './timepicker/filter/timepicker-filter.component';
import {TimepickerNavigationComponent} from './timepicker/navigation/timepicker-navigation.component';
import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-validation.component';
import {DropdownPositionComponent} from './dropdown/position/dropdown-position.component';
@@ -63,6 +64,7 @@ export const routes: Routes = [
path: 'timepicker',
children: [
{path: 'navigation', component: TimepickerNavigationComponent},
+ {path: 'filter', component: TimepickerFilterComponent},
]
},
];
diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.component.html b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.html
new file mode 100644
index 0000000000..b57cf189d4
--- /dev/null
+++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.html
@@ -0,0 +1,4 @@
+
diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts
new file mode 100644
index 0000000000..0801a0fe7e
--- /dev/null
+++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts
@@ -0,0 +1,8 @@
+import {Component} from '@angular/core';
+
+@Component({
+ templateUrl: './timepicker-filter.component.html',
+})
+export class TimepickerFilterComponent {
+ time = {hour: null, minute: null, second: null};
+}
diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts b/e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts
new file mode 100644
index 0000000000..7a0f8c64d5
--- /dev/null
+++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts
@@ -0,0 +1,69 @@
+import {protractor} from 'protractor';
+
+import {openUrl} from '../../tools.po';
+
+import {TimepickerFilterPage} from './timepicker-filter.po';
+
+describe('Timepicker', () => {
+ let page: TimepickerFilterPage;
+
+ beforeAll(() => page = new TimepickerFilterPage());
+ beforeEach(async() => await openUrl('timepicker/filter'));
+
+ async function expectValue(expectedValue) {
+ const inputs = page.getFields();
+
+ const values = [];
+ for (let i = 0; i < inputs.length; i++) {
+ values[i] = await inputs[i].getAttribute('value');
+ }
+ expect(values.join(':')).toBe(expectedValue);
+ }
+
+ describe('filter', async() => {
+ it(`should accept numbers`, async() => {
+ await expectValue('::'); // No starting values
+
+ const inputs = page.getFields();
+ await inputs[0].sendKeys('1');
+ await inputs[1].sendKeys('2');
+ await inputs[2].sendKeys('3');
+
+ await inputs[0].click();
+ await expectValue('01:02:03');
+ });
+
+ it(`shouldn't accept alpha`, async() => {
+ await expectValue('::'); // No starting values
+
+ const inputs = page.getFields();
+ await inputs[0].sendKeys('A');
+ await inputs[1].sendKeys('A');
+ await inputs[2].sendKeys('A');
+
+ await inputs[0].click();
+ await expectValue('::');
+ });
+
+ it(`shouldn accept special commands`, async() => {
+
+ const inputs = page.getFields();
+
+ await inputs[0].sendKeys('1');
+ await inputs[0].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a'));
+ await inputs[0].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'c'));
+
+ await inputs[1].click();
+ await inputs[1].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'v'));
+
+ await inputs[2].click();
+ await inputs[2].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'v'));
+
+ await inputs[0].click();
+ await expectValue('01:01:01');
+
+ });
+
+ });
+
+});
diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts b/e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts
new file mode 100644
index 0000000000..fd3012578a
--- /dev/null
+++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts
@@ -0,0 +1,8 @@
+import {$} from 'protractor';
+
+export type Field = 'hour' | 'minute' | 'second';
+
+export class TimepickerFilterPage {
+ getField(field: Field) { return $(`.ngb-tp-${field} > input`); }
+ getFields() { return ['hour', 'minute', 'second'].map((field: Field) => this.getField(field)); }
+}
diff --git a/src/timepicker/timepicker.ts b/src/timepicker/timepicker.ts
index 2ff2ccddbf..056aeb236c 100644
--- a/src/timepicker/timepicker.ts
+++ b/src/timepicker/timepicker.ts
@@ -15,6 +15,8 @@ import {NgbTimepickerConfig} from './timepicker-config';
import {NgbTimeAdapter} from './ngb-time-adapter';
import {NgbTimepickerI18n} from './timepicker-i18n';
+const timepickerFilterRegExp = /[^0-9]/g;
+
const NGB_TIMEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgbTimepicker),
@@ -38,10 +40,12 @@ const NGB_TIMEPICKER_VALUE_ACCESSOR = {
Increment hours
-