Primeng: Keyboard Support for Table Row Selection

Created on 18 May 2018  路  8Comments  路  Source: primefaces/primeng

I'm submitting a ... (check one with "x")

[ ] bug report => Search github for a similar issue or PR before submitting
[ x ] feature request => Please check if request is not on the roadmap already https://github.com/primefaces/primeng/wiki/Roadmap
[ ] support request => Please do not submit support request here, instead see http://forum.primefaces.org/viewforum.php?f=35

Current behavior
Arrow keys scroll the table body up/down

Expected behavior
Allow arrow keys to change the selected row to the next/previous record.

This feature references #5209 and #713

new feature

Most helpful comment

Coming soon in 7.0.

All 8 comments

As a temporary fix, a simple directive that intercepts keys from p-table component.

import { Directive, ElementRef, OnInit, HostListener } from '@angular/core';
import { Table } from 'primeng/table';

@Directive({
  selector: 'p-table'
})
export class TurboTableKeysDirective implements OnInit {

  constructor(private table: Table, private el: ElementRef<HTMLElement>) {}

  ngOnInit() {
    this.el.nativeElement.tabIndex = 1;
  }

  @HostListener('keydown.ArrowUp', ['$event']) ArrowUp($event: KeyboardEvent) {
    this.table.selection = this.navigateItem(-1);
    this.table.onRowSelect.emit({originalEvent: $event, data: this.table.selection, type: 'row'});
    event.preventDefault();
  }

  @HostListener('keydown.ArrowDown', ['$event']) ArrowDown($event: KeyboardEvent) {
    this.table.selection = this.navigateItem(1);
    this.table.onRowSelect.emit({originalEvent: $event, data: this.table.selection, type: 'row'});
    event.preventDefault();
  }

  navigateItem(num) {
    if (!this.table.selection) { return; }
    const i = this.table.value.indexOf(this.table.selection);
    const len = this.table.value.length;
    if (num > 0) {
      return this.table.value[(i + num) % len];
    }
    return this.table.value[(i + len + num) % len];
  }

}

Small scroll improvement:

import { Directive, ElementRef, OnInit, HostListener } from '@angular/core';
import { Table } from 'primeng/table';

@Directive({
  selector: 'p-table'
})
export class TurboTableKeysDirective implements OnInit {

    constructor(private table: Table, private el: ElementRef<HTMLElement>) {}

    ngOnInit() {
        this.el.nativeElement.tabIndex = 1;
    }

    @HostListener('keydown.ArrowUp', ['$event']) ArrowUp($event: KeyboardEvent) {
        this.table.selection = this.navigateItem(-1);
        this.table.onRowSelect.emit({originalEvent: $event, data: this.table.selection, type: 'row'});
        event.preventDefault();
        this.doScroll();
    }

    @HostListener('keydown.ArrowDown', ['$event']) ArrowDown($event: KeyboardEvent) {
        this.table.selection = this.navigateItem(1);
        this.table.onRowSelect.emit({originalEvent: $event, data: this.table.selection, type: 'row'});
        event.preventDefault();
        this.doScroll();
    }

    navigateItem(num) {
        if (!this.table.selection) { return; }
        const i = this.table.value.indexOf(this.table.selection);
        const len = this.table.value.length;
        if (num > 0) {
            return this.table.value[(i + num) % len];
        }
        return this.table.value[(i + len + num) % len];
    }

    private doScroll() {
        let index = this.table.selection ? this.table.value.findIndex(item => item.id == this.table.selection.id) : 0;
        let scrollBodyEl = this.table.el.nativeElement.getElementsByClassName('ui-table-scrollable-body')[0];
        let tbodyEl = scrollBodyEl.getElementsByClassName('ui-table-tbody')[0];
        if (!tbodyEl.children.length)
            return;
        let rowEl = tbodyEl.children[index];
        if (rowEl.offsetTop < scrollBodyEl.scrollTop)
            scrollBodyEl.scrollTop = rowEl.offsetTop;
        else if ((rowEl.offsetTop + rowEl.offsetHeight) > (scrollBodyEl.scrollTop + scrollBodyEl.offsetHeight - 17)) {
            scrollBodyEl.scrollTop += rowEl.offsetTop + rowEl.offsetHeight - scrollBodyEl.scrollTop - scrollBodyEl.offsetHeight + 17;
        }
    }
}

Any news about this (if it will be implemented in the next release or not).

Coming soon in 7.0.

@cagataycivici just wondering if this was released in 7.0.0

@cagataycivici Were this released in 7.0?

@Thor- Thanks for the solution. https://github.com/primefaces/primeng/issues/5762#issuecomment-412077141
Please improve it to handle multiple row selection when user presses shift+up/down to select multiple rows and unselect if already selected.

@cagataycivici, Is this feature available in the latest version (v8)?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

just-paja picture just-paja  路  3Comments

markgoho picture markgoho  路  3Comments

Helayxa picture Helayxa  路  3Comments

cyberrranger picture cyberrranger  路  3Comments

pchristou picture pchristou  路  3Comments