Skip to content

Commit 90930d6

Browse files
committed
fix(datepicker): move focus into start input when pressing backspace on end input
Makes it so that pressing backspace on an empty end input moves focus into the start input. This makes the two separate inputs feel a bit more like a single input.
1 parent 5dd582c commit 90930d6

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

src/material/datepicker/date-range-input-parts.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
ErrorStateMatcher,
3939
} from '@angular/material/core';
4040
import {BooleanInput} from '@angular/cdk/coercion';
41+
import {BACKSPACE} from '@angular/cdk/keycodes';
4142
import {MatDatepickerInputBase, DateFilterFn} from './datepicker-input-base';
4243
import {DateRange, MatDateSelectionModel} from './date-selection-model';
4344

@@ -47,6 +48,8 @@ export interface MatDateRangeInputParent<D> {
4748
min: D | null;
4849
max: D | null;
4950
dateFilter: DateFilterFn<D>;
51+
_startInput: MatDateRangeInputPartBase<D>;
52+
_endInput: MatDateRangeInputPartBase<D>;
5053
_groupDisabled: boolean;
5154
_ariaDescribedBy: string | null;
5255
_ariaLabelledBy: string | null;
@@ -319,5 +322,14 @@ export class MatEndDate<D> extends _MatDateRangeInputBase<D> implements CanUpdat
319322
}
320323
}
321324

325+
_onKeydown(event: KeyboardEvent) {
326+
// If the user is pressing backspace on an empty end input, focus focus back to the start.
327+
if (event.keyCode === BACKSPACE && !this._elementRef.nativeElement.value) {
328+
this._rangeInput._startInput.focus();
329+
}
330+
331+
super._onKeydown(event);
332+
}
333+
322334
static ngAcceptInputType_disabled: BooleanInput;
323335
}

src/material/datepicker/date-range-input.spec.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import {MatNativeDateModule} from '@angular/material/core';
77
import {MatDatepickerModule} from './datepicker-module';
88
import {MatFormFieldModule} from '@angular/material/form-field';
99
import {MatInputModule} from '@angular/material/input';
10-
import {dispatchFakeEvent} from '@angular/cdk/testing/private';
10+
import {dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing/private';
1111
import {FocusMonitor} from '@angular/cdk/a11y';
12+
import {BACKSPACE} from '@angular/cdk/keycodes';
1213
import {MatDateRangeInput} from './date-range-input';
1314
import {MatDateRangePicker} from './date-range-picker';
1415

@@ -473,6 +474,34 @@ describe('MatDateRangeInput', () => {
473474
expect(fixture.componentInstance.end).toBe(end);
474475
}));
475476

477+
it('should move focus to the start input when pressing backspace on an empty end input', () => {
478+
const fixture = createComponent(StandardRangePicker);
479+
fixture.detectChanges();
480+
const {start, end} = fixture.componentInstance;
481+
482+
spyOn(start.nativeElement, 'focus').and.callThrough();
483+
484+
end.nativeElement.value = '';
485+
dispatchKeyboardEvent(end.nativeElement, 'keydown', BACKSPACE);
486+
fixture.detectChanges();
487+
488+
expect(start.nativeElement.focus).toHaveBeenCalled();
489+
});
490+
491+
it('should move not move focus when pressing backspace if the end input has a value', () => {
492+
const fixture = createComponent(StandardRangePicker);
493+
fixture.detectChanges();
494+
const {start, end} = fixture.componentInstance;
495+
496+
spyOn(start.nativeElement, 'focus').and.callThrough();
497+
498+
end.nativeElement.value = '10/10/2020';
499+
dispatchKeyboardEvent(end.nativeElement, 'keydown', BACKSPACE);
500+
fixture.detectChanges();
501+
502+
expect(start.nativeElement.focus).not.toHaveBeenCalled();
503+
});
504+
476505
});
477506

478507
@Component({

tools/public_api_guard/material/datepicker.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ export declare class MatEndDate<D> extends _MatDateRangeInputBase<D> implements
367367
constructor(rangeInput: MatDateRangeInputParent<D>, elementRef: ElementRef<HTMLInputElement>, defaultErrorStateMatcher: ErrorStateMatcher, injector: Injector, parentForm: NgForm, parentFormGroup: FormGroupDirective, dateAdapter: DateAdapter<D>, dateFormats: MatDateFormats);
368368
protected _assignValueToModel(value: D | null): void;
369369
protected _getValueFromModel(modelValue: DateRange<D>): D | null;
370+
_onKeydown(event: KeyboardEvent): void;
370371
static ngAcceptInputType_disabled: BooleanInput;
371372
static ɵdir: i0.ɵɵDirectiveDefWithMeta<MatEndDate<any>, "input[matEndDate]", never, {}, {}, never>;
372373
static ɵfac: i0.ɵɵFactoryDef<MatEndDate<any>, [null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;

0 commit comments

Comments
 (0)