1

I am loading the user table data to ligtning datatable. Intially the page loads, I load all the user list list to front end and using pagination Im going through the records instead going to the server again. Based on the list we can deactivate the users or exclude the user using a checkbox.

Initially all checkbox should come as true but only first page will checked as true. The other pages checkboxes are not checked. Pre selected Row Ids are send to the UI via controller to checked or unchecked. Another issue I faced is the selected checkboxes are not selected when move to another page and coming back to the same page. The selected Ids will be send to the system by clicking the Deactivate Users button.

The Page 1 Checkboxes are pre selected as below,

Page 2 other any other pages checkboxes are not selected. (selected-rows= {preSelectedRows})

Wrapper Class

public class UserMngtWrapper {

//User Id
public String UserId {get; set;}
public String FullName {get; set;}
public String Email {get; set;}
//User ProfileName
public String ProfileName {get; set;}
//User RoleName
public String RoleName {get; set;}
//User is Frozen
public String isFrozen {get; set;}
//User Last Login Date
public Datetime LastLoginDate {get; set;}
//User Last Modified Date by user
public String LastModifiedDate {get; set;}
//User Created Date
public String CreatedDate {get; set;}
//User is Active
public String isActive {get; set;}
//User is Deactivated
public String isDeactivate {get; set;}
}

Controller

public class UserManagementController {

@AuraEnabled(cacheable=true)
public static string getUserList() {
    List<UserMngtWrapper> userMngtWrapperList = new List<UserMngtWrapper>();
    UserListMngtWrapper userListMngtWrapper = new UserListMngtWrapper();
    Set<Id> selectedIdSet = new Set<Id>();
    //Get last two months inactive users
    Set<ID> inactiveUserIds = new Map<Id,User>([SELECT id From User
                                                WHERE LastLoginDate < LAST_N_DAYS: 60
                                                      AND IsActive = TRUE                                                                                                                
                                                      AND CreatedDate < LAST_N_DAYS: 60
                                                ]).keySet();
    //Get last two months inactive users Data
    List<User> userList = [Select  id,Profile.Name,Name,Email,UserRole.Name,LastLoginDate,LastModifiedDate,CreatedDate,IsActive,IsDeactivate__c   FROM User where id= : inactiveUserIds order by Profile.Name asc,Name asc];
    
    for (User u : userList)
    {
        UserMngtWrapper userMngtWrapper = new UserMngtWrapper();
        userMngtWrapper.UserId = u.id;
        userMngtWrapper.FullName = (u.Name != null ) ? u.Name: '';
        userMngtWrapper.Email = (u.Email != null ) ? u.Email: '';
        userMngtWrapper.LastLoginDate =  u.LastLoginDate;
        userMngtWrapper.ProfileName =  (u.Profile.Name != null ) ? u.Profile.Name: '';
        userMngtWrapper.RoleName =  (u.UserRole.Name != null ) ? u.UserRole.Name: '';
        userMngtWrapper.isDeactivate =  (u.IsDeactivate__c == false  ) ? 'FALSE': 'TRUE' ;
        userMngtWrapperList.add(userMngtWrapper);
        selectedIdSet.add(u.Id);
    }

    userListMngtWrapper.userMngtWrapperList = userMngtWrapperList;
    userListMngtWrapper.selectedUserIdSet = selectedIdSet;
    return JSON.serialize(userListMngtWrapper);
}


@AuraEnabled(cacheable=true)
public static Boolean userRecordsUpdate() {
   // inprogress
    Return true;
}

**Wrapper List Class**
public class UserListMngtWrapper{
    @AuraEnabled public List<UserMngtWrapper> userMngtWrapperList {get; set;}
    @AuraEnabled public set<Id> selectedUserIdSet {get; set;}
}

HTML

import { LightningElement , track, wire,api } from 'lwc';
import getUserList from '@salesforce/apex/UserManagementController.getUserList';
import userRecordsUpdate from '@salesforce/apex/UserManagementController.userRecordsUpdate';
import {refreshApex} from '@salesforce/apex';

export default class Usermanagement extends LightningElement {
 @track  columns = [
    { label: 'User Id',fieldName: 'UserId',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,},
    { label: 'Name',fieldName: 'FullName',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,},
    { label: 'Email',fieldName: 'Email',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,},
    { label: 'Profile Name',fieldName: 'ProfileName',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,},
    { label: 'Role Name',fieldName: 'RoleName',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,},
    {
            label: "Last Login Date",
            fieldName: "LastLoginDate",
            type: "date",
            typeAttributes:{
                year: "numeric",
                month: "2-digit",
                day: "2-digit",
                hour: "2-digit",
                minute: "2-digit",
                second: "2-digit"
            },
            sortable: false,cellAttributes: { alignment: 'left' },
            initialWidth: 200,
        },
        { label: 'Deactivate',fieldName: 'isDeactivate',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}

];

     @track showLoadingSpinner = false;
     @track error;
     @track page = 1;
     @track perpage = 5;
     @track pages = [];
     @track disabledConditionNext =false;
     @track disabledConditionPrev =false;
     @track disabledCondition = true;
     @track preSelectedRows=[];
     @track totalRecordCount=0;
     data=[];
     @track numberOfPages =1;
     numOfPreviousPages;
     set_size = 5;
     
     connectedCallback() {
        this.init();
     }
    
     async init()
     {
                 try {
                this.disabledCondition = true;
                this.showLoadingSpinner = true;
                await getUserList()
                 .then((result,error) => {
                     var userList = JSON.parse(result);

                     if (userList) {
this.data=userList.userMngtWrapperList;
                         this.preSelectedRows = userList.selectedUserIdSet;
                         this.data = this.data;
                        this.totalRecordCount = this.data.length;
                     } else if (error) {
                         console.error(error);
                     }
                 });
                    this.disabledConditionPrev =false;
                    this.disabledConditionNext =false;
                    this.disabledCondition = false;
                    this.setPages(this.data);
                    this.showLoadingSpinner = false;

             } catch (error) {
                      this.error = error;
                  } finally {
                      this.showLoadingSpinner = false;
                  }
         }
         
         get currentPageData(){
                       return this.pageData();
                    }
         
         get pagesList(){
        let mid = Math.floor(this.set_size/2) + 1 ;
        if(this.page > mid){
            return this.pages.slice(this.page-mid, this.page+mid-1);
        }
            return this.pages.slice(0,this.set_size);
     }
     
        pageData = ()=>{
                             let numberOfPages = Math.ceil(this.data.length / this.perpage);
                             this.numberOfPages = numberOfPages;
                             let page = this.page;
                             let perpage = this.perpage;
                             let startIndex = (page*perpage) - perpage;
                             let endIndex = (page*perpage);
                             if(this.numberOfPages < 1)
                             {
                                this.disabledConditionPrev =true;
                                this.disabledConditionNext =true;
                             }
                             return this.data.slice(startIndex,endIndex);
                          }

        setPages = (data)=>{
                                      let numberOfPages = Math.ceil(data.length / this.perpage);
                                      this.numOfPreviousPages = numberOfPages;

                                  }


        onNext = ()=>{
                                      if(this.page < this.numberOfPages){
                                         ++this.page;
                                          this.disabledConditionNext =false;
                                          this.disabledConditionPrev =false;
                                          this.hasPageChanged =true;
                                         
                                      }
                                      else {
                                          this.disabledConditionNext =true;                            this.disabledConditionPrev =false;

                                      }

                                  }

        onPrev = ()=>{
                                      if(this.page > 1){
                                            --this.page;
                                            this.disabledConditionPrev =false;
                                            this.disabledConditionNext =false;
                                      }
                                      else {
                                            this.disabledConditionPrev =true;
                                            this.disabledConditionNext =false;
                                      }
                                  }

      onFirst = ()=>{
              this.page = 1;
              }

      onLast = ()=>{
              this.page = this.numberOfPages;
              }

              onPageClick = (e)=>{
                        this.page = parseInt(e.target.dataset.id,10);
                        if(this.numberOfPages < 1)
                        {
                            this.disabledConditionPrev =true;
                            this.disabledConditionNext =true;
                        }
                        else
                        {
                             this.disabledConditionPrev =false;
                             this.disabledConditionNext =false;
                        }
                    }

       // Method didnt develop and test
    updateRecords(){
             var selectedRecords =
              this.template.querySelector("lightning-datatable").getSelectedRows();
              let arrset = [];
              selectedRecords.forEach(row => {
                                 arrset.push(row.userId);
                             });
              userRecordsUpdate()
             .then(result=>{
               return refreshApex(this.refreshTable);
             })
             .catch(error=>{
               alert('Could not update(error));
             })
           }

HTML

<template>
    <lightning-card   title="User Management" icon-name="standard:user" class="slds-col slds-size_12-of-12 slds-p-top_small">
        <lightning-button slot="actions" label="Deactivate Users" onclick={updateRecords}></lightning-button>
        <div class="slds-p-left_medium">
            <div class="slds-col slds-size_12-of-12 slds-p-top_medium">
                <div class="slds-p-around_medium lgc-bg">

                    <lightning-datatable
                            key-field="UserId"
                            columns={columns}
                            data={currentPageData}
                            selected-rows= {preSelectedRows}
                            onrowaction={getRowActions}
                            >
                    </lightning-datatable>
                </div>

                <div class="slds-col slds-size_10-of-12 slds-p-top_medium">
                    <lightning-layout multiple-rows="true">
                        <lightning-layout-item size = "12" margin= "around-small">
                            <div class="slds-align_absolute-center">
                                <ul class="slds-button-group-row">
                                    <li class="slds-button-group-item" >
                                        <button class="slds-button slds-button_neutral" disabled={disabledCondition} onclick ={onFirst}> First
                                        </button>
                                    </li>
                                    <li class="slds-button-group-item" >
                                        <button class="slds-button slds-button_neutral" disabled={disabledConditionPrev} onclick ={onPrev}> Prev
                                        </button>
                                    </li>

                                    <li class="slds-button-group-item" >
                                        <button class="slds-button slds-button_neutral"  disabled={disabledConditionNext} onclick={onNext} >Next</button>
                                    </li>
                                    <li class="slds-button-group-item" >
                                        <button class="slds-button slds-button_neutral"  disabled={disabledCondition} onclick ={onLast}> Last
                                        </button>
                                    </li>
                                </ul>
                            </div>
                            </br>
                            <div class="slds-align_absolute-center" >
                                <span>Total Records: {totalRecordCount} </span>
                            </div>
                            <div class="slds-align_absolute-center" >
                                <span>Page ({page} of {numberOfPages}) </span>
                            </div>


                        </lightning-layout-item>
                    </lightning-layout>
                </div>
            </div>
        </div>
        <div if:true={showLoadingSpinner}>
            <lightning-spinner alternative-text="Loading" size="large"></lightning-spinner>
        </div>
    </lightning-card>
</template>

I am loading the user table data to datatable using LWC, the users who has not logging past two months. When the page loads first time I load all the list to front end and using pagination Im going through the records instead going to the server again. Based on the list we can deactivate the users or exclude the user using a checkbox.

Initially all checkbox should come as true but only first page will checked as true. The other pages checkboxes are not checked. Pre selected Row Ids are send to the UI via controller to checked or unchecked. Another issue I faced is the selected checkboxes are not selected when move to another page and coming back to the same page. The selected Ids will be send to the system by clicking the Deactivate Users button.

Page 1 Pre selected Rows checkbox as true

Page 2 or others Pre selected Rows checkbox are not checked

Wrapper Class

public class UserMngtWrapper {

//User Id public String UserId {get; set;} //User FullName public String FullName {get; set;} //User Email public String Email {get; set;} //User ProfileName public String ProfileName {get; set;} //User RoleName public String RoleName {get; set;} //User Last Login Date public Datetime LastLoginDate {get; set;} //User is Deactivated public String isDeactivate {get; set;} } Controller

public class UserManagementController {

@AuraEnabled(cacheable=true) public static string getUserList() { List userMngtWrapperList = new List(); UserListMngtWrapper userListMngtWrapper = new UserListMngtWrapper(); Set selectedIdSet = new Set(); //Get last two months inactive users Set inactiveUserIds = new Map<Id,User>([SELECT id From User WHERE LastLoginDate < LAST_N_DAYS: 60 AND IsActive = TRUE
AND CreatedDate < LAST_N_DAYS: 60 ]).keySet(); //Get last two months inactive users Data List userList = [Select id,Profile.Name,Name,Email,UserRole.Name,LastLoginDate,LastModifiedDate,CreatedDate,IsActive,IsDeactivate__c FROM User where id= : inactiveUserIds order by Profile.Name asc,Name asc];

for (User u : userList)
{
    UserMngtWrapper userMngtWrapper = new UserMngtWrapper();
    userMngtWrapper.UserId = u.id;
    userMngtWrapper.FullName = (u.Name != null ) ? u.Name: '';
    userMngtWrapper.Email = (u.Email != null ) ? u.Email: '';
    userMngtWrapper.LastLoginDate =  u.LastLoginDate;
    userMngtWrapper.ProfileName =  (u.Profile.Name != null ) ? u.Profile.Name: '';
    userMngtWrapper.RoleName =  (u.UserRole.Name != null ) ? u.UserRole.Name: '';
    userMngtWrapper.isDeactivate =  (u.IsDeactivate__c == false  ) ? 'FALSE': 'TRUE' ;
    userMngtWrapperList.add(userMngtWrapper);
    selectedIdSet.add(u.Id);
}

userListMngtWrapper.userMngtWrapperList = userMngtWrapperList;
userListMngtWrapper.selectedUserIdSet = selectedIdSet;
return JSON.serialize(userListMngtWrapper);

}

Wrapper List Class public class UserListMngtWrapper{ @AuraEnabled public List userMngtWrapperList {get; set;} @AuraEnabled public set selectedUserIdSet {get; set;} } }

JS

import { LightningElement , track, wire,api } from 'lwc'; import getUserList from '@salesforce/apex/UserManagementController.getUserList'; import userRecordsUpdate from '@salesforce/apex/UserManagementController.userRecordsUpdate'; import {refreshApex} from '@salesforce/apex';

export default class Usermanagement extends LightningElement { @track columns = [ { label: 'User Id',fieldName: 'UserId',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}, { label: 'Name',fieldName: 'FullName',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}, { label: 'Email',fieldName: 'Email',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}, { label: 'Profile Name',fieldName: 'ProfileName',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}, { label: 'Role Name',fieldName: 'RoleName',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}, { label: "Last Login Date", fieldName: "LastLoginDate", type: "date", typeAttributes:{ year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" }, sortable: false,cellAttributes: { alignment: 'left' }, initialWidth: 200, }, { label: 'Deactivate',fieldName: 'isDeactivate',type: 'text',sortable: false,cellAttributes: { alignment: 'left' },initialWidth: 200,}

];

 @track showLoadingSpinner = false;
 @track error;
 @track page = 1;
 @track perpage = 5;
 @track pages = [];
 @track disabledConditionNext =false;
 @track disabledConditionPrev =false;
 @track disabledCondition = true;
 @track preSelectedRows=[];
 @track totalRecordCount=0;
 data=[];
 @track numberOfPages =1;
 numOfPreviousPages;
 set_size = 5;
 
 connectedCallback() {
    this.init();
 }

 async init()
 {
             try {
            this.disabledCondition = true;
            this.showLoadingSpinner = true;
            await getUserList()
             .then((result,error) => {
                 var userList = JSON.parse(result);

                 if (userList) {

this.data=userList.userMngtWrapperList; this.preSelectedRows = userList.selectedUserIdSet; this.data = this.data; this.totalRecordCount = this.data.length; } else if (error) { console.error(error); } }); this.disabledConditionPrev =false; this.disabledConditionNext =false; this.disabledCondition = false; this.setPages(this.data); this.showLoadingSpinner = false;

         } catch (error) {
                  this.error = error;
              } finally {
                  this.showLoadingSpinner = false;
              }
     }
     
     get currentPageData(){
                   return this.pageData();
                }
     
     get pagesList(){
    let mid = Math.floor(this.set_size/2) + 1 ;
    if(this.page > mid){
        return this.pages.slice(this.page-mid, this.page+mid-1);
    }
        return this.pages.slice(0,this.set_size);
 }
 
    pageData = ()=>{
                         let numberOfPages = Math.ceil(this.data.length / this.perpage);
                         this.numberOfPages = numberOfPages;
                         let page = this.page;
                         let perpage = this.perpage;
                         let startIndex = (page*perpage) - perpage;
                         let endIndex = (page*perpage);
                         if(this.numberOfPages < 1)
                         {
                            this.disabledConditionPrev =true;
                            this.disabledConditionNext =true;
                         }
                         return this.data.slice(startIndex,endIndex);
                      }

    setPages = (data)=>{
                                  let numberOfPages = Math.ceil(data.length / this.perpage);
                                  this.numOfPreviousPages = numberOfPages;

                              }


    onNext = ()=>{
                                  if(this.page < this.numberOfPages){
                                     ++this.page;
                                      this.disabledConditionNext =false;
                                      this.disabledConditionPrev =false;
                                      this.hasPageChanged =true;
                                     
                                  }
                                  else {
                                      this.disabledConditionNext =true;                            this.disabledConditionPrev =false;

                                  }

                              }

    onPrev = ()=>{
                                  if(this.page > 1){
                                        --this.page;
                                        this.disabledConditionPrev =false;
                                        this.disabledConditionNext =false;
                                  }
                                  else {
                                        this.disabledConditionPrev =true;
                                        this.disabledConditionNext =false;
                                  }
                              }

  onFirst = ()=>{
          this.page = 1;
          }

  onLast = ()=>{
          this.page = this.numberOfPages;
          }

          onPageClick = (e)=>{
                    this.page = parseInt(e.target.dataset.id,10);
                    if(this.numberOfPages < 1)
                    {
                        this.disabledConditionPrev =true;
                        this.disabledConditionNext =true;
                    }
                    else
                    {
                         this.disabledConditionPrev =false;
                         this.disabledConditionNext =false;
                    }
                }

HTML

                <lightning-datatable
                        key-field="UserId"
                        columns={columns}
                        data={currentPageData}
                        selected-rows= {preSelectedRows}
                        onrowaction={getRowActions}
                        >
                </lightning-datatable>
            </div>

            <div class="slds-col slds-size_10-of-12 slds-p-top_medium">
                <lightning-layout multiple-rows="true">
                    <lightning-layout-item size = "12" margin= "around-small">
                        <div class="slds-align_absolute-center">
                            <ul class="slds-button-group-row">
                                <li class="slds-button-group-item" >
                                    <button class="slds-button slds-button_neutral" disabled={disabledCondition} onclick ={onFirst}> First
                                    </button>
                                </li>
                                <li class="slds-button-group-item" >
                                    <button class="slds-button slds-button_neutral" disabled={disabledConditionPrev} onclick ={onPrev}> Prev
                                    </button>
                                </li>

                                <li class="slds-button-group-item" >
                                    <button class="slds-button slds-button_neutral"  disabled={disabledConditionNext} onclick={onNext} >Next</button>
                                </li>
                                <li class="slds-button-group-item" >
                                    <button class="slds-button slds-button_neutral"  disabled={disabledCondition} onclick ={onLast}> Last
                                    </button>
                                </li>
                            </ul>
                        </div>
                        </br>
                        <div class="slds-align_absolute-center" >
                            <span>Total Records: {totalRecordCount} </span>
                        </div>
                        <div class="slds-align_absolute-center" >
                            <span>Page ({page} of {numberOfPages}) </span>
                        </div>
                    </lightning-layout-item>
                </lightning-layout>
            </div>
        </div>
    </div>
    <div if:true={showLoadingSpinner}>
        <lightning-spinner alternative-text="Loading" size="large"></lightning-spinner>
    </div>
</lightning-card>
Expand snippet Summarize the Issues are,
  1. Pre selected Row Ids are only selected or checked in page 1. Not checked in other pages.
  2. The selected checkboxes are not selected(checked box unchecked) after move to another page and coming back to the same page. Selected items should remain even going though any paginations and come back to the same page.

Could you please help me on this. Thank you in advance

2 Answers 2

1

You need to keep a separate list of all selections in one variable, then update this variable accordingly as you navigate pages (and also keep track of any changes).

allSelectedRows = [];
preselectedRows = [];
changePage(pageNumber) {
    let pageData = this.getPageData();
    this.allSelectedRows = this.allSelectedRows
        .filter((rowId) => !pageData.find((record) => record.UserId === rowId)) // Preserve rows outside current page
        .concat(this.template.querySelector('lightning-datatable').selectedRows); // and add rows from current page
    this.page = pageNumber;
    pageData = this.getPageData();
    this.preslectedRows = this.allSelectedRows.filter(
        (rowId) => pageData.find((record) => record.UserId === rowId) // And now find records in current page
    );
}
onFirst() {
    this.changePage(1);
}
onNext() {
    this.changePage(this.page + 1);
}
// ... etc ...

Also, some general notes...

First, don't use await and then() together:

try {
// other code here
  let userList = await getUserList();
  // rest of code here
} catch(error) {
  this.error = error;
}
this.showLoadingSpinner = false;

Or:

getUserList().then(
  userList => {
    // success logic here
  })
  .catch(error => this.error = error)
  .finally(() => this.showLoadingSpinner = false);

Second, you really didn't need to JSON.serialize and JSON.parse, you can return the wrappers directly.

2
  • Thank you soo much @sfdcfox for quickly helping me out on this. I have worked on two days on this and I was unable to resolve this. You have given solution for Pre selected Row Ids are only selected or checked in page 1. And Pre Selected Row Ids are showing properly in other pages too.. But still im facing the selected/deselect checkboxes are not maintaining state across the pages. when I deselect two elements in page one and move to next page and comeback to same page 1 deselect items are selected again. Selected or deselected items not remain same when going though the paginations.
    – lochana
    Apr 7, 2021 at 9:19
  • It showing same initial pre selected Ids checked again even Im deselected and moving to another page and come back to same page again. Is there way to remove deselected ids from the same list inside changePage(pageNumber) function. Thank you for the general notes as well, I will change my code according to that.
    – lochana
    Apr 7, 2021 at 9:19
0

Lightning data-table easily helps us to show large data in tabular format, with a flexible selection approach.

When pagination applies with the LWC: Datatable pre-selected-rows, it does not work straightforward way. Because apply pagination helps to display only selected page information and hide the rest of the records actually they are not populated yet.

So when you want to know about the selected rows from the data table, it gives you results in only the current page information not persist the previous or next page configured selected records.

To resolve the selection issue, we need to store the selected records page-wise.

When the user selects any page, the storage helps to populate his previous selected options. If he has done any new selection update. The system will also update the storage with the newly selected option.

This process is implemented in the below article

https://www.linkedin.com/pulse/lwc-datatable-way-programmatically-handle-preselect-siddiquee/

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .