Wyatt
Wyatt

Reputation: 523

React maintain focus position after clicking on different element

I have a two column table. The right column has input fields. When an input field is focused (as shown in picture below), it displays a non focusable button on the right side of the table. When the user clicks this button, it should modify the focused input field with it's text but reversed. This button is non TABable.

My problem is that when the user clicks the button to reverse the text, it unfocuses his current position in the table. Meaning, when he clicks tab again after clicking the button, the focus goes back to the top of the page instead of continuing from the input box that just got reversed.

How can I retain the tab position even when the user clicks on other non TABable elements?

enter image description here

Upvotes: 1

Views: 2212

Answers (1)

Seth Lutske
Seth Lutske

Reputation: 10792

Your best tactic is to keep track of what element is currently focused on in a global state variable. When each element is focused on, whether through clicking on it or tabbing onto it, you have to detect the change in focus and update the state variable which is keeping track of that. That means that each of your table cells that is tabable needs an eventListener for onFocus that updates the state variable. Then you can attach an event listener to your button which will shift the focus to the adjascent cell. So if your table looks like this:

<table>
  <tr>
    <td class="title">Source</td>
    <td class="title">Note</td>
  </tr>
  <tr>
    <td id="1" tabindex="1">Climbing</td>
    <td id="2" tabindex="2">I really like this sport</td>
  </tr>
  <tr>
    <td id="3" tabindex="3">Running</td>
    <td id="4" tabindex="4">Meh not a fan</td>
  </tr>
  <tr>
    <td id="5" tabindex="5">Biking</td>
    <td id="6" tabindex="6">I need a bike</td>
  </tr>
  <tr>
    <td id="7" tabindex="7">Eating</td>
    <td id="8" tabindex="8">who isnt a fan</td>
  </tr>
</table>

<button id="toggleButton">Toggle focus</toggle>

You can set up some basic JS like so:

// global state variable
let currentlyFocusedElement;

const tds = document.querySelectorAll('td')

// attach onFocus events to all your tabable boxes
tds.forEach( td => {
  td.addEventListener('focus', () => {
    currentlyFocusedElement = td
    console.log(currentlyFocusedElement)
  })
})

const toggleButton = document.querySelector('#toggleButton')

// use the button to change the focus programmatically
// my if statements here are a little slapdash, but they work to solve your problem, can be easily adjusted
toggleButton.addEventListener('click', () => {
  const number = currentlyFocusedElement.id
  console.log(number)
  if (number % 2 === 0){
    document.getElementById(`${number-1}`).focus()
  } else if (number % 2 === 1) {
    document.getElementById(Number(number)+1).focus()
  }
})

I made a working example here: codepen tab thing

Of course after writing this all up I saw that your question has a reactjs tag and it makes me wish you would have been way more specific in your question and even included your code. I'm sure you can adapt some of my vanilla js solution to a react environment.

Upvotes: 1

Related Questions