Home > OS >  Programmatic row selection in a p-table using selectionMode 'multiple'
Programmatic row selection in a p-table using selectionMode 'multiple'

Time:11-15

I have a PrimeNG v12.2 p-table component abbreviated as follows:

<p-table
   [(selection)]="selectedMessages"
   selectionMode="multiple">

I need to programmatically select the row the user just clicked on. I figured I would just push a new object to selectedMessages in the click, but it does not work. The object is pushed, but nothing remains selected.

I need to handle the right-click. The row is defined as:

<tr (contextmenu)="clickMessage(message)">

The event is handled with:

clickMessage(mail: MailboxItem): void {
    this.selectedMessages.push(mail);
}

The member is initialized to empty:

selectedMessages: MailboxItem[] = [];

My event fires properly, the object goes from empty ([]) to having one MailboxItem in it, but no table rows are selected.

CodePudding user response:

I'm sorry, I can't test this now, but I guess you should put the id of your MailboxItem object as "dataKey" in your table.

For instance, if your mail rows are getting value from an array like this:

mailsArray: MailboxItem[]  =
[ 
 { 
   myId=1; 
   from="Patrick"; 
   message="Blah,blah,bla..";
 },
 { 
   myId=2; 
   from="Swaiczwe"; 
   message="Lorem blahblah etceterabla..";
 }
];

then your table should had a dataKey attibute like this:

<p-table
   [(selection)]="selectedMessages"
   selectionMode="multiple"
   [value]="mailsArray"
   dataKey="myId"
>

And finally, your method clickMessage() should be like this:

clickMessage(mail: MailboxItem): void {
    this.selectedMessages.push(mail.myID);
}

You should put also something similar to this in yours header and body templates (sorry, but you didn't show how you have it, so it's approximate):

<ng-template pTemplate="header">
   <tr [pSelectableRow]="mail">
                <th>Id</th>
                <th>From</th>
                <th>Message</th>
   </tr>
</ng-template>

<ng-template pTemplate="body" let-mail  let-rowIndex="rowIndex">
            <tr [pSelectableRow]="mail" [pSelectableRowIndex]="rowIndex">
                <td>{{mail.myId}}</td>
                <td>{{mail.from}}</td>
                <td>{{mail.message}}</td>
            </tr>
</ng-template>

P.S: Also try changing

<ng-template pTemplate="header">
   <tr [pSelectableRow]="mail">

just to a 'simple' , like this:

<ng-template pTemplate="header">
   <tr>

CodePudding user response:

The issue here is that Angular change detection only occurs when the array bound to [(selection)] is modified.

The solution is to re-assign to the array itself which will trigger change detection and properly select the row:

this.selectedMessages = [...this.selectedMessages, mail];

In my use-case we want to de-select all rows except the one being right-clicked on, so it is simply:

this.selectedMessages = [ mail ];
  • Related