0

I have a table with three columns. In the first column is text and in the second and third are input fields. Within the row I can navigate with keyCode to the right, but when I reach the last column then I can not jump to the next row. What do I have to add to my code to make this possible?

My StackBlitz: https://stackblitz.com/edit/angular-wmfjhh-vhkikf?file=app%2Ftable-basic-example.ts

Code:

// Snippet from HTML
<tbody formArrayName="rows" *ngIf="rows && rows !== null && !isLoading">
      <tr class="optimize-row" *ngFor="let rowControl of rows.controls; let rowIndex = index">
        <td [formGroupName]="rowIndex" *ngFor="let column of displayedColumns; let columnIndex = index;">
          <div *ngIf="attributesWithFormControls.includes(column.attribute); else otherColumns">
            <span>
              <label>
                <input style="background-color: silver" [id]="'row-' + rowIndex + '-col-' + columnIndex" type="text" arrow-div [formControl]="rowControl.get(column.attribute)" (focus)="onFocus($event)">
              </label>
            </span>
          </div>
          <ng-template #otherColumns>
            <div tabindex="0" [id]="'row-' + rowIndex + '-col-' + columnIndex" arrow-div>
              Here is a Number
            </div>
          </ng-template>
        </td>
      </tr>
    </tbody>
// TS
/**
   * Use arrowKey
   * @param object any
   */
  move(object) {
    console.log('move', object);

    const id = object.element.nativeElement.id;

    console.log(id);

    const arr = id.split('-');
    let row: number = Number(arr[1]);
    let col: number = Number(arr[3]);
    switch (object.action) {
      case 'UP':
        --row;
        break;
      case 'DOWN':
        ++row;
        break;
      case 'LEFT':
        --col;
        break;
      case 'RIGTH':
        ++col;
        break;
    }
    this.setFocus(row, col);
  }

 onFocus(event: FocusEvent): void {
    console.log('onFocus', event.target);

    const target = event.target as HTMLElement;

    if (target.tagName === 'INPUT') {
      this.currentInputInFocus = target;
    }
  }

  private setFocus(row: number, col: number) {
    console.log(`setFocus [row:${row}] [col:${col}]`);
    const newElementToFocusOn = document.getElementById(
      `row-${row}-col-${col}`
    );
    if (newElementToFocusOn) {
      console.log('focusing');
      this.currentInputInFocus = newElementToFocusOn;
      this.currentInputInFocus.focus();
    }
  }
Alireza Ahmadi
  • 8,579
  • 5
  • 15
  • 42
  • Does this answer your question? [How can I set an automatic focus in the input for a keyCode navigation?](https://stackoverflow.com/questions/68600391/how-can-i-set-an-automatic-focus-in-the-input-for-a-keycode-navigation) – Aviad P. Aug 01 '21 at 08:16
  • I test your code with `Down` key you can navigate to next row. what is the problem? Do you want to navigate next row with `ArrowRight` and `ArrowLeft`? – Alireza Ahmadi Aug 01 '21 at 08:35
  • Exactly. I want to be able to navigate with right and left into other rows. Do you know how to do that? –  Aug 01 '21 at 08:37

2 Answers2

0

You just need some more condition on your switch case based on count of your input:

For example if your col is greater than 2 (note that you can use dynamic number based on your number of input per row) which means you need to go next line so, you need to increase the row value too:

if(col > 2)
         {
           row++;
           col = 0;
         }

Also same as thing for previous line:

  switch (object.action) {
  case 'UP':
    --row;
    break;
  case 'DOWN':
    ++row;
    break;
  case 'LEFT':
    --col;
    if(col < 0)
    {
      row--;
      col = 2;
    }
    break;
  case 'RIGTH':
    ++col;
    if(col > 2)
     {
       row++;
       col = 0;
     }
    break;
}

Here is working sample on stackblitz

Alireza Ahmadi
  • 8,579
  • 5
  • 15
  • 42
  • cool, but what I realize when testing that the right left navigation only works in the inputs. Is there a way that the first column is taken into account? –  Aug 01 '21 at 08:57
0

Inside your move function and in case when user was clicked on the right button, you have to check if the col is at the table's last column, if yes increment the row by one, and reset the col to zero, else increment the col only.

**You can do the opposite when user was clicked on the left and when it gets to the table's first column

Your switch case should looks like this

switch (object.action) {
  case 'UP':
    --row;
    break;
  case 'DOWN':
    ++row;
    break;
  case 'LEFT':
    if (col === 0) {
      --row;
      col = 2;
    } else {
      --col;
    }
    break;
  case 'RIGTH':
    if (col === 2) {
      ++row;
      col = 0;
    } else {
      ++col;
    }
    break;
}

See sample: stackblitz