4

I am working with a PrimeNG table, and am trying to select the row of a pSelectableRow by keypress.

I have a global search input that will filter all results of the table, and when the user is done searching, I would like them to be able to click a button on the keyboard and have the row selected from the filtered options.

Currently, if a user is searching and the input box has the focus, they can press tab , but they must press 5 times in order to get down to to first row (more if there are more columns).

Is it possible to select a row element within the app component via typescript or other method where on a keypress, the first row would be selected? Then of course, the user could press enter to actually select the row. The up and down arrows work once the rows are active, but you need to get to the rows first.

I have set up a hotkey function inside of my app so that the f1 key triggers an event:

this.addShortcut({ keys: 'f1' }).subscribe(() => {
  this.showMessage();
  console.log(this.table.value);
});

This is showing a message from the PrimeNG message service to make sure the hotkey is working, and it is also logging the value of the table to the console. I have looked through the table and there doesn't seem to be any way of selecting a row. I have tried setting the this.table.selection = this.table.value[1] and this does store the [1] array item as the "selected value", but this does not actually select any item from the table.

Is there a better way of doing this? For simplicity of the code required to make this reproducible in StackOverflow, I have included a stackblitz instead. Here is a stackblitz.

Antikhippe
  • 6,316
  • 2
  • 28
  • 43
Jeremy
  • 1,038
  • 11
  • 34

1 Answers1

2

If you add [(selection)]="selectedProduct" (onFilter)="onFilter($event, dt)" to your table declaration in your component, then you can manage your table selection every time the user makes a search this way:

onFilter(event, dt) {
    if (event.filteredValue.length > 0) {
      this.selectedProduct = event.filteredValue[0]; // set first visible row as selected
    }
  }

See StackBlitz

Is that what you are looking for?

Edit:

Ok, I hope I've understood your need. I added three HostListener to navigate along the filtered data and execute an action while pressing Enter key:

  @HostListener('keydown.ArrowUp', ['$event']) ArrowUp($event: KeyboardEvent) {
    if (this.cpt > 0) {
      this.cpt--;
    }
    this.selectedProduct = this.visibleProducts[this.cpt];
  }

  @HostListener('keydown.ArrowDown', ['$event']) ArrowDown(
    $event: KeyboardEvent
  ) {
    if (this.cpt < this.visibleProducts.length - 1) {
      this.cpt++;
    }
    this.selectedProduct = this.visibleProducts[this.cpt];
  }

  @HostListener('keydown.Enter', ['$event']) Enter($event: KeyboardEvent) {
    alert('opening product: ' + this.selectedProduct.name);
  }

And now, the onFilter method looks like:

  onFilter(event, dt) {
    this.cpt = 0;
    if (event.filteredValue.length > 0) {
      this.selectedProduct = event.filteredValue[0];
      this.visibleProducts = event.filteredValue;
    }
  }
Antikhippe
  • 6,316
  • 2
  • 28
  • 43
  • The look of this is similar, but the functionality is not quite. What the user would need to do is select a row with the `enter` key. In the example here, the row is "selected", but when enter is pressed, it does not trigger the `(onRowSelect)` . Ideally, the user should type something in the search box and then can arrow up/down into the table to "select" (highlight) a row, then click `enter` to actually select it. For example, this here: https://imgur.com/okwUfZK shows a selected row where the user can now click `enter` . They would ideally need to go up and down between row items as well – Jeremy Oct 05 '21 at 14:49
  • Please check updated Stackblitz and tell me if it's ok or not. – Antikhippe Oct 08 '21 at 10:03
  • 1
    This looks good. After your first reply I thought that may be a good way to implement it. I really like what you've done, thanks for your help – Jeremy Oct 10 '21 at 21:19