New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(datepicker): add keyboard navigation #1273
feat(datepicker): add keyboard navigation #1273
Conversation
2ad3d45
to
76f5994
Compare
ea6bee6
to
efcae51
Compare
efcae51
to
6ccfa4d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks!
A couple of comments I have:
- The only big concern I have is that now keyboard focusing and navigation between months are very much tied to each other in the code.
I would have done focus handling as an optional service that works with the datepicker. Now it starts to get huge, so I think we should think about something like that. Currently 25% of the datapicker.ts
code is focus handling
- I'm not sure everybody would want to have the keyboard support ON all the time. Like for time range selection cases, etc. But this could be optionally turned off later I guess
Minor comments:
- when two months are displayed, clicking on navigation arrows changes focus between months, when it should do navigation actually
- please order members/methods alphabetically
src/datepicker/datepicker.spec.ts
Outdated
return event; | ||
} | ||
|
||
function triggerFocus(element: DebugElement) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused function I suppose
src/datepicker/datepicker.ts
Outdated
@@ -250,17 +260,26 @@ export class NgbDatepicker implements OnChanges, | |||
} | |||
} | |||
|
|||
onDateSelect(date: NgbDate) { | |||
this._setViewWithinLimits(date); | |||
isDisplayedDateSelectable(date: NgbDate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be private _isDisplayedDateSelectable
src/datepicker/datepicker.ts
Outdated
break; | ||
} | ||
|
||
this._updateData(); | ||
} | ||
|
||
@HostListener('keydown', ['$event']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other components the events are usually grouped in the host
like so:
(keydown): onKeyDown($event)
I think I would prefer to do the same here to quickly see what kind of handlers we have on the datepicker
src/datepicker/datepicker.ts
Outdated
return; | ||
} | ||
switch (event.keyCode) { | ||
case 33 /* page up */: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In rating
and typeahead
we have an enum Keys
that contains key codes (and ideally should be shared), so switch reads like: case Key.PageUp:
Not sure which one I prefer though...
src/datepicker/datepicker.ts
Outdated
} | ||
|
||
@HostListener('blur', ['$event']) | ||
onBlur(event: FocusEvent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be '(blur)': 'focusedDate = null'
I suppose
src/datepicker/datepicker.ts
Outdated
break; | ||
} | ||
|
||
this._updateData(); | ||
} | ||
|
||
@HostListener('keydown', ['$event']) | ||
onKeyDown(event: KeyboardEvent) { | ||
let focusedDate = this.focusedDate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be const
, or just use this.focusedDate
altogether?
src/datepicker/datepicker.ts
Outdated
@@ -310,6 +416,46 @@ export class NgbDatepicker implements OnChanges, | |||
} | |||
} | |||
|
|||
private getFirstDisplayedDate() { return this.months[0].firstDate; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
method name should start with _
src/datepicker/datepicker.ts
Outdated
@@ -310,6 +416,46 @@ export class NgbDatepicker implements OnChanges, | |||
} | |||
} | |||
|
|||
private getFirstDisplayedDate() { return this.months[0].firstDate; } | |||
|
|||
private getLastDisplayedDate() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
method name should start with _
8ad8679
to
f03190d
Compare
@maxokorokov Thank you for your review. I have pushed some changes following your comments. Regarding the idea of implementing keyboard navigation as a separate service, I had actually asked the question to @pkozlowski-opensource but he had answered to keep it simple in the same file for now. |
f03190d
to
97e6d91
Compare
cd1e3f7
to
fd7d0b3
Compare
@maxokorokov I have rebased this PR and resolved the conflict with the master branch. Do you think it could be merged soon? |
As we've discussed @divdavem, we'll try to refactor this quite a bit:
|
The following shortcuts are available: Arrow left/right: previous/next day Arrow up/down: previous/next week Page up/down: previous/next month Shift+page up/down: previous/next year Home/end: beginning/end of the current view Shift+home/end: min/max selectable date
fd7d0b3
to
94bbea1
Compare
Moved everything from from here in the #1551, closing this one. |
The following keyboard shortcuts are now available:
Arrow left/right: previous/next day
Arrow up/down: previous/next week
Page up/down: previous/next month
Shift+page up/down: previous/next year
Home/end: beginning/end of the currently displayed month(s)
Shift+home/end: min/max selectable date
Note that the previous/next month and previous/next year shortcuts should probably keep the current day in the previous/next month and the current month in the previous/next year. I think this should be implemented by a change in the behavior of getNext/getPrev in ngb-calendar. This probably has to be discussed, especially with @maxokorokov who designed this API. I have opened another PR about it: #1277