I have a custom listbox, a div
that contains a vertical list of other div
children. I want to add an up/down arrows keys navigation to change which child is currently selected.
So when I click the first item and press the down arrow key
, it should allow me to select the second item (following item). And if I click the up arrow key
, it should select back the first item (previous item).
const renderInboxSummary = targetDetailsData.map((todo, index) => {
const hasNewMessageInd = todo.hasNewMessageInd;
return (
<div onClick={() => this.handleClick(targetDetailsData, todo.aprReference, index)}>
<div>
{todo.aprRecordUserName}
</div>
<div>
{todo.aprBranchCode}
</div>
<div>
{todo.aprScreeName}
</div>
</div>
);
});
Every div
has a click event handler this.handleClick(targetDetailsData, todo.aprReference, index)
.
I have a custom listbox, a div
that contains a vertical list of other div
children. I want to add an up/down arrows keys navigation to change which child is currently selected.
So when I click the first item and press the down arrow key
, it should allow me to select the second item (following item). And if I click the up arrow key
, it should select back the first item (previous item).
const renderInboxSummary = targetDetailsData.map((todo, index) => {
const hasNewMessageInd = todo.hasNewMessageInd;
return (
<div onClick={() => this.handleClick(targetDetailsData, todo.aprReference, index)}>
<div>
{todo.aprRecordUserName}
</div>
<div>
{todo.aprBranchCode}
</div>
<div>
{todo.aprScreeName}
</div>
</div>
);
});
Every div
has a click event handler this.handleClick(targetDetailsData, todo.aprReference, index)
.
1 Answer
Reset to default 15This can be done by using a ref
in ReactJS and then adding an event listener for the keydown
event and then moving the focus to the next or previous sibling.
Notes
- I add
tabindex
attribute to each div to allow them to be focused upon - I use a
ref
on the wrapping element to listen forkeydown
- I check
keycode
for up/down to move to next/previous sibling - I believe the
keycode
for up/down on a full size keyboard is different, but I don't have one to test.
Solution
To test the demo, click on any div and then use up/down arrows
const { Component } = React;
class App extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
this.moveFocus();
}
moveFocus() {
const node = this.myRef.current;
node.addEventListener('keydown', function(e) {
const active = document.activeElement;
if(e.keyCode === 40 && active.nextSibling) {
active.nextSibling.focus();
}
if(e.keyCode === 38 && active.previousSibling) {
active.previousSibling.focus();
}
});
}
render() {
return (
<div ref={this.myRef}>
<div tabindex="0">First</div>
<div tabindex="1">Second</div>
<div tabindex="2">Third</div>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
div:focus {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Documentation
https://reactjs.org/docs/refs-and-the-dom.html
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex