0

I have an ordered table with a field on one entity which you can change to "re-rank" that row on the table:

 <table>
  <thead>
    <th>Rank</th>
    <th>Name</th>
  </thead>
  <tbody>
    <tr *ngFor="let entity of entities">
      <td>
        <input *ngIf='entity === currentEntity' 
                value="{{entity.Rank}}" 
                type="number" 
                min="1"
                max="{{entities.length}}"
                (change)="updateRank(entity, $event)">
        <span *ngIf='entity !== currentEntity'>{{entity.Rank}}</span>
      </td>
      <td>
        <span>{{entity.Name}}</span>
      </td>
    </tr>
  </tbody>
</table>

So the number input is only for the current entity, and on a change, I re-rank these in the back-end and update the ordering on the UI.

This works great, but the issue is that when you are using the arrow keys to change the rank, the focus is only preserved when decreasing the rank. When you increase the rank, the focus is removed from the input box.

JsFiddle: https://jsfiddle.net/JustinDao/t0hwLu4b/ (try on Chrome or Firefox)

I think this is due to how Angular creates the DOM elements, but I'm not entirely sure. Is there a way for me to preserve the focus when increasing the rank as well?

justindao
  • 2,273
  • 4
  • 18
  • 34
  • 1
    I don't understand the requirement (what exactly you're achieving). Temporary solution : https://jsfiddle.net/shantanu_k/tswk8acn/ – Shantanu Sep 20 '18 at 18:22
  • I want the user to be able to use the arrow keys to re-rank the rows on the table easily. I see that your fiddle does just that! Why do you need the setTimeout() here? – justindao Sep 20 '18 at 18:27
  • There's a bug in your code - it uses Angular instead of React. (jk jk jk) – Andy Barron Sep 20 '18 at 18:40
  • 1
    https://jsfiddle.net/JustinDao/mcu1tb90/ Here is a fiddle with @Shantanu 's fix, with a slightly more elegant way to grab the object (passing it into the method itself) https://stackoverflow.com/questions/33955650 seems to be the explanation of why this works - the DOM element doesn't exist yet, so you queue a message with `.focus()` so that the DOM updates, then the `.focus()` call is made. Thanks! – justindao Sep 20 '18 at 18:58

1 Answers1

0

http://jsfiddle.net/JustinDao/mcu1tb90

The fix is to do a setTimeout to set the focus on the input.

Passing the input object into the method:

<input #myInput
       *ngIf='entity === currentEntity' 
       value="{{entity.Rank}}" 
       type="number" 
       min="1"
       max="{{entities.length}}"
       (change)="updateRank(entity, $event, myInput)">

Then in updateRank

updateRank(entity, event, inputObject) {
    ....
    setTimeout(() => {
        inputObject.focus();
    });
}

http://stackoverflow.com/questions/33955650 has an explanation of why this works. Basically, the DOM element doesn't exist yet, so you queue a message with .focus() by using setTimeout so that the DOM updates, then the .focus() call is made.

justindao
  • 2,273
  • 4
  • 18
  • 34