how to change the tab index to go to the next listview-same cell instead of the next cell in the same listview

0
as mentioned, we have a list of rows. the client does the first column first, then the 2nd column. the client would like to navigate using the tab key.   I have tried setting the tabIndex of the first cell to 1, and the second cell to 2. but this did not result in the desired effect.   has anyone else found a way to do this without rebuilding my domain model?         edit: found this, might be helpful for someone Tabbing through page https://community.mendix.com/link/space/user-experience/questions/92170   Tried adding an expression, as I can probably calculate this in the background to calculate the order, but doesn't work.
asked
1 answers
0

I tried a few different approaches, and unfortunately, the default tabbing behavior in HTML tables is to move horizontally—cell by cell within the same row—before jumping to the first cell of the next row. I tested this behavior with a regular HTML table, a table inside a List View like the one shown earlier, and even with Data Grid 2. In all cases, I came to the conclusion that tabbing proceeded horizontally.

It turned into a delightful pair programming session with ChatGPT 😉 I noticed that in a Mendix List View, each <li> gets a unique mx-name-index-X class. That gave me the idea to intercept the Tab key, detect which <td> the focused input is in (i.e. which column), then identify the current row based on the <li> index, and finally focus the input in the same column of the next row.

 

One tricky part was timing: I initially tried to calculate everything during the keydown event, but the browser's default behavior would already start changing the focus before I could run my logic. By using e.preventDefault() and delaying the focus logic slightly using setTimeout(..., 0), I was able to reliably override the default tab behavior and focus vertically instead of horizontally. I also added Shift+Tab support to allow vertical tabbing both up and down.

Here’s the script that ended up working. It might need some tweaking depending on your specific DOM structure or widget setup—I only tested it in the browser console so far. I left the console.warn() statements in for debugging; feel free to remove those when you're done testing 😉

 

document.querySelectorAll('.mx-textbox input').forEach(input => {
  input.addEventListener('keydown', function (e) {
    if (e.key === 'Tab') {
      e.preventDefault(); // Always prevent default behavior

      const goingDown = !e.shiftKey;
      const direction = goingDown ? 1 : -1;

      const currentInput = this;
      const currentTd = currentInput.closest('td');
      const currentListItem = currentInput.closest('li');

      const allTds = Array.from(currentTd?.parentElement?.children || []);
      const colIndex = allTds.indexOf(currentTd);

      const listItems = Array.from(currentListItem?.parentElement?.querySelectorAll('li') || []);
      const currentIndex = listItems.indexOf(currentListItem);
      const targetIndex = currentIndex + direction;
      const targetItem = listItems[targetIndex];

      console.warn(`Tab ${goingDown ? '↓' : '↑'}: From row ${currentIndex} to ${targetIndex}, col ${colIndex}`);

      setTimeout(() => {
        if (!targetItem) {
          console.warn('No target list item found.');
          return;
        }

        const targetTds = targetItem.querySelectorAll('td');
        const targetTd = targetTds[colIndex];

        if (!targetTd) {
          console.warn(`No TD found in column ${colIndex} of target row.`);
          return;
        }

        const targetInput = targetTd.querySelector('input, textarea, [tabindex]');
        if (targetInput) {
          console.warn('Focusing input in target row/column');
          targetInput.focus();
        } else {
          console.warn('No focusable element found in target TD.');
        }
      }, 0);
    }
  });
});

 

 

answered