• Accueil / Salesforce / Comment implémenter la…
, Comment implémenter la pagination dans Lightning Web Component &#8211; SFDCPanther<span class="wtr-time-wrap after-title"><span class="wtr-time-number">10</span> minutes de lecture</span>

Comment implémenter la pagination dans Lightning Web Component – SFDCPanther10 minutes de lecture


Chers #Trailblazers, #Ohana,

Dans cet article, je vais vous montrer comment créer un composant Web Pagination Lightning réutilisable que vous pouvez utiliser pour n’importe quel composant pour afficher les données sous forme de tableau ou sous toute autre forme que vous souhaitez afficher.

Fonctionnalités disponibles dans le composant

  1. Affichez les enregistrements dans un tableau ou dans un autre format.
  2. Edition en ligne pour la table de données LWC
  3. Tri dans la table de données LWC
  4. Prend en charge l’action au niveau de la ligne
  5. Affiche les détails de la page et le nombre d’enregistrements

Avant, nous commençons à travailler sur les implémentations, parlons du concept de Pagination.

La pagination est l’une de ces fonctionnalités ennuyeuses qui ne sont pas amusantes à implémenter dans aucune langue, mais qui est à peu près essentielle pour une bonne interface utilisateur.

Lorsque nous parlons de pagination, nous avons généralement une liste d’enregistrements et nous voulions ensuite afficher ces enregistrements sur de nombreuses pages.

Donc, si nous disons que nous récupérons des enregistrements de la liste (nous pouvons également dire découper les enregistrements comme nous découpons le gâteau) et les afficher sur la page. Vous trouverez ci-dessous la mise en œuvre étape par étape de la pagination à l’aide de JavaScript.

1. Quelques variables utiles


var recordList; // The List of Complete Records
var pageList; // The record List which needs to be displayed in a page
var currentPage = 1;
// by default will always be 1
var recordPerPage = 10;
 // The no of records needs to be displayed in a single page
var totalPages = 1;   // calculates the total number of pages

2. Calculer le nombre de pages

this.totalPages = Math.ceil(recordList.length / recordPerPage );

3. Créez des boutons de navigation et leurs méthodes.

Dans Pagination, nous recherchons généralement 4 boutons de navigation principaux.

  1. Première
  2. précédent
  3. Prochain
  4. Dernier
handleNext() {
        this.pageNo += 1;
        this.preparePaginationList();
    }

    handlePrevious() {
        this.pageNo -= 1;
        this.preparePaginationList();
    }

    handleFirst() {
        this.pageNo = 1;
        this.preparePaginationList();
    }

    handleLast() {
        this.pageNo = this.totalPages;
        this.preparePaginationList();
    }

4. Préparez les enregistrements de pagination

let begin = (this.pageNo - 1) * parseInt(this.recordsperpage);
let end = parseInt(begin) + parseInt(this.recordsperpage);
this.recordsToDisplay = this.records.slice(begin, end);

Dans le code ci-dessus, nous utilisons la méthode slice de JavaScript pour obtenir l’enregistrement exact basé sur le numéro de page afin que nous puissions afficher les enregistrements corrects sur la page.

Créer un composant doPagination

Code HTML

Code JsvaScript

import { LightningElement, api, track } from "lwc";
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

const DELAY = 300;

export default class DoPaginaton extends LightningElement {

    @api showTable = false;
    @api records;
    @api recordsperpage;
    @api columns;

    @track draftValues = [];
    @track recordsToDisplay;

    totalRecords;
    pageNo;
    totalPages;
    startRecord;
    endRecord;
    end = false;
    pagelinks = [];
    isLoading = false;
    defaultSortDirection = 'asc';
    sortDirection = 'asc';
    ortedBy;

    connectedCallback() {
        this.isLoading = true;
        this.setRecordsToDisplay();
    }
    setRecordsToDisplay() {
        this.totalRecords = this.records.length;
        this.pageNo = 1;
        this.totalPages = Math.ceil(this.totalRecords / this.recordsperpage);
        this.preparePaginationList();

        for (let i = 1; i  this.totalRecords ? this.totalRecords : end;
        this.end = end > this.totalRecords ? true : false;

        const event = new CustomEvent('pagination', {
            detail: { 
                records : this.recordsToDisplay
            }
        });
        this.dispatchEvent(event);

        window.clearTimeout(this.delayTimeout);
        this.delayTimeout = setTimeout(() => {
            this.disableEnableActions();
        }, DELAY);
        this.isLoading = false;
    }

    disableEnableActions() {
        let buttons = this.template.querySelectorAll("lightning-button");

        buttons.forEach(bun => {
            if (bun.label === this.pageNo) {
                bun.disabled = true;
            } else {
                bun.disabled = false;
            }

            if (bun.label === "First") {
                bun.disabled = this.pageNo === 1 ? true : false;
            } else if (bun.label === "Previous") {
                bun.disabled = this.pageNo === 1 ? true : false;
            } else if (bun.label === "Next") {
                bun.disabled = this.pageNo === this.totalPages ? true : false;
            } else if (bun.label === "Last") {
                bun.disabled = this.pageNo === this.totalPages ? true : false;
            }
        });
    }

    handleRowAction(event) {
        const actionName = event.detail.action.name;
        const row = event.detail.row;
        const rowAction = new CustomEvent('actions', {
            detail: { 
                actionName : actionName,
                data : row
            }
        });
        this.dispatchEvent(rowAction);
    }

    handlePage(button) {
        this.pageNo = button.target.label;
        this.preparePaginationList();
    }

    onHandleSort(event) {
        const { fieldName: sortedBy, sortDirection } = event.detail;
        const cloneData = [...this.recordsToDisplay];
        cloneData.sort(this.sortBy(sortedBy, sortDirection === 'asc' ? 1 : -1));
        this.recordsToDisplay = cloneData;
        this.sortDirection = sortDirection;
        this.sortedBy = sortedBy;
    }
    sortBy( field, reverse, primer ) {

        const key = primer
        ? function( x ) {
            return primer(x[field]);
        }
        : function( x ) {
            return x[field];
        };

        return function( a, b ) {
            a = key(a);
            b = key(b);
            return reverse * ( ( a > b ) - ( b > a ) );
        };
    }

    handleSave(event) {
        this.isLoading = true;
        const recordInputs =  event.detail.draftValues.slice().map(draft => {
            const fields = Object.assign({}, draft);
            return { fields };
        });
        const promises = recordInputs.map(recordInput => updateRecord(recordInput));
        window.console.log(' Updating Records.... ');
        Promise.all(promises).then(record => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'All Records updated',
                    variant: 'success'
                })
            );
            this.draftValues = [];
            eval("$A.get('e.force:refreshView').fire();");
            return refreshApex(this.recordsToDisplay);
        }).catch(error => {
            window.console.error(' error **** n '+error);
        })
        .finally(()=>{
            this.isLoading = false;
        })
    }
}

Code CSS

.customSelect select {
    padding-right: 1.25rem;
    min-height: inherit;
    line-height: normal;
    height: 1.4rem;
}
.customSelect label {
    margin-top: 0.1rem;
}
.customSelect .slds-select_container::before {
    border-bottom: 0;
}
.customInput {
    width: 3rem;
    height: 1.4rem;
    text-align: center;
    border: 1px solid #dddbda;
    border-radius: 3px;
    background-color: #fff;
}

Propriétés publiques dans le composant

Ce composant possède les propriétés suivantes qui doivent être transmises par le parent où vous souhaitez utiliser la table de données.

  1. showTable – Accepte vrai / faux. Si vrai, il affichera la table de données.
  2. records – La liste complète des enregistrements
  3. enregistrements par page – N’accepte aucune valeur et définit le nombre d’enregistrements devant être affichés sur une seule page.
  4. Colonnes – si la valeur de la propriété showTable est true, elle nécessite la colonne de données valide. Pour plus de détails, visitez ici.

Événements dans le composant

Ce composant contient

  1. pagination – Cet événement envoie la liste de tous les enregistrements qui sont affichés sur la page actuelle et à utiliser si vous ne souhaitez pas utiliser Lightning Data Table pour afficher les enregistrements. Par exemple, vous vouliez utiliser l’accordéon Lightning pour la pagination au lieu de la table de données.
  2. Actions – Cet événement envoie les données sur la ligne actuelle et l’action au niveau de la ligne. Ainsi, si vous avez des actions au niveau de la ligne, vous pouvez gérer cet événement dans votre composant parent.

Testez le composant de pagination.

Pour tester cela, vous devez créer une classe Apex qui renverra une liste d’enregistrements. J’ai utilisé la requête ci-dessous.

public with sharing class ContactController {
    @AuraEnabled
    public static List getContacts() {
        List contactList = [
            SELECT
                Id,
                Name,
                AccountId,
                Account.Name,
                Title,
                Phone,
                Email,
                OwnerId,
                Owner.Name,
                Owner.Email
            FROM CONTACT
            WITH SECURITY_ENFORCED
        ];
        return contactList;
    }
}

Créez le composant Lightning et appelez le composant doPagination à l’intérieur de ce composant.


Si vous avez remarqué cela, nous transmettons la valeur de la propriété requise et gérons les événements requis dont nous avons discuté ci-dessus.

Voici le code complet du composant de test

HTML


Code JS

/**
 * @File Name          : contactDataTable.js
 * @Description        : 
 * @Author             : A Singh
 * @Group              : 
 * @Last Modified By   : Amit Singh
 * @Last Modified On   : 12-06-2020
 * @Modification Log   : 
 * Ver       Date            Author      		    Modification
 * 1.0    6/5/2020   A Singh     Initial Version
**/
import { LightningElement, track } from 'lwc';
import getContacts from '@salesforce/apex/ContactController.getContacts';
import sharedjs from 'c/sharedjs';

const columns = [
    { label: 'Name', fieldName: 'Name', wrapText: 'true', sortable: true, editable: true },
    { label: 'Email', fieldName: 'Email', type: 'email', sortable: true, editable: true },
    { label: 'Phone', fieldName: 'Phone', type: 'phone', sortable: true, editable: true },
    { label: 'Title', fieldName: 'Title', sortable: true, editable: true },
    {
        label: 'Account',
        fieldName: 'ACC_NAME',
        wrapText: 'true',
        cellAttributes: {
            iconName: { fieldName: 'accIconName' },
            iconPosition: 'left'
        },
        sortable: true
    },
    {
        label: 'Owner',
        fieldName: 'OWNER',
        cellAttributes: {
            iconName: { fieldName: 'iconName' },
            iconPosition: 'left'
        },
        sortable: true
    },

    {
        label: 'View',
        fieldName: 'URL',
        type: 'url',
        wrapText: 'true',
        typeAttributes: {
            tooltip: { fieldName: 'Name' },
            label: {
                fieldName: 'Name'
            },
            target: '_blank'
        }
    },
    { label: 'View', type:  'button', typeAttributes: { 
            label: 'View',  name: 'View',  variant: 'brand-outline',
            iconName: 'utility:preview', iconPosition: 'right'
        } 
    },
];
export default class ContactDataTable extends LightningElement {
    @track records;
    @track errors;
    columns = columns;

    connectedCallback() {
        this.handleDoInit();
    }
    handleDoInit() {
        sharedjs._servercall(
            getContacts,
            undefined,
            this.handleSuccess.bind(this),
            this.handleError.bind(this)
        );
    }

    handleSuccess(result) {
        result.forEach(element => {
            if (element.OwnerId) {
                element.OWNER = element.Owner.Name;
                element.iconName = 'standard:user';
            }
            if (element.AccountId) {
                element.ACC_NAME = element.Account.Name;
                element.accIconName = 'standard:account';
            }
            element.URL = 'https://' + window.location.host + '/' + element.Id;
        });
        this.records = result;
        this.errors = undefined;
    }
    handleError(error) {
        this.errors = error;
        this.records = undefined;
    }

    handleRowActions(event){
        window.console.log(' Row Level Action Handled ', event.detail.actionName);
        window.console.log(' Row Level Action Handled ', JSON.stringify(event.detail.data));
    }

    handlePagination(event){
        //window.console.log('Pagination Action Handled ', JSON.stringify(event.detail.records));
    }
}

Fichier .XML



    50.0
    true
    Contact Data Table
    
        lightning__RecordPage
        lightning__AppPage
        lightning__HomePage
        lightningCommunity__Page
        lightningCommunity__Default
    

Créer un composant SharedJs

Le composant de test ci-dessus a la dépendance d’un nouveau composant Web Lightning et ci-dessous se trouve le code JS pour le même composant.

/* eslint-disable no-else-return */
/**
 * @File Name          : sharedjs.js
 * @Description        :
 * @Author             : [email protected]
 * @Group              :
 * @Last Modified By   : Amit Singh
 * @Last Modified On   : 12-06-2020
 * @Modification Log   :
 * Ver       Date            Author      		    Modification
 * 1.0    5/17/2020   [email protected]     Initial Version
 **/
import { ShowToastEvent } from "lightning/platformShowToastEvent";

    /*
        ! To store all the JS functions for the various LWC
        * This JavaScript file is used to provide many reusability functionality like pubsub 
        * Reusable Apex Calls to Server, Preparing Dynamic Toasts
        Todo : PubSub JS file of LWC & Aura Components
        ? V2
    */

    var callbacks = {};

    /**
     * Registers a callback for an event
     * @param {string} eventName  - Name of the event to listen for.
     * @param {function} callback - Function to invoke when said event is fired.
     */
    const subscribe = (eventName, callback) => {
    if (!callbacks[eventName]) {
        callbacks[eventName] = new Set();
    }
    callbacks[eventName].add(callback);
    };

    /**
     * Unregisters a callback for an event
     * @param {string} eventName - Name of the event to unregister from.
     * @param {function} callback - Function to unregister.
     */
    const unregister = (eventName, callback) => {
    if (callbacks[eventName]) {
        callbacks[eventName].delete(callback);
        // ! delete the callback from callbacks variable
    }
    };

    const unregisterAll = () => {
        callbacks = {};
    };

    /**
     * Fires an event to listeners.
     * @param {string} eventName - Name of the event to fire.
     * @param {*} payload - Payload of the event to fire.
     */
    const publish = (eventName, payload) => {
    if (callbacks[eventName]) {
        callbacks[eventName].forEach(callback => {
        try {
            callback(payload);
        } catch (error) {
            // fail silently
        }
        });
    }
    };

/**
 * Todo: Calls an Apex Class method and send the response to call back methods.
 * @param {*} _serveraction     - Name of the apex class action needs to execute.
 * @param {*} _params           - the list of parameters in JSON format
 * @param {*} _onsuccess        - Name of the method which will execute in success response
 * @param {*} _onerror          - Name of the method which will execute in error response
 */
    const _servercall = (_serveraction, _params, _onsuccess, _onerror) => {
    if (!_params) {
        _params = {};
    }
    _serveraction(_params)
        .then(_result => {
        if (_result && _onsuccess) {
            _onsuccess(_result);
        }
        })
        .catch(_error => {
        if (_error && _onerror) {
            _onerror(_error);
        }
        });
    };

    /**
     * Todo: Prepare the toast object and return back to the calling JS class
     * @param {String} _title     - title of of the toast message
     * @param {String} _message   - message to display to the user
     * @param {String} _variant   - toast type either success/error/warning or info
     * @param {String} _mode      - defines either toast should auto disappear or it should stick.
     */
    const _toastcall = (_title, _message, _variant, _mode) => {
        const _showToast = new ShowToastEvent({
            title: _title,
            message: _message,
            mode: _mode,
            variant: _variant
        });
        return _showToast;
    };

/**
     * Todo: Parse the Error message and returns the parsed response to calling JS method.
     * @param {Array} errors  - Error Information
     */
    const _reduceErrors = errors => {
    if (!Array.isArray(errors)) {
        errors = [errors];
    }
    return errors
        .filter(error => !!error)
        .map(error => {
        if (Array.isArray(error.body)) {
            return error.body.map(e => e.message);
        } else if (error.body && typeof error.body.message === "string") {
            return error.body.message;
        } else if (typeof error.message === "string") {
            return error.message;
        }
        return error.statusText;
        })
        .reduce((prev, curr) => prev.concat(curr), [])
        .filter(message => !!message);
    };

/*
    Todo: Export all the functions so that these are accisible from the other JS Classes
*/
export default {
    subscribe,
    unregister,
    publish,
    unregisterAll,
    _servercall,
    _toastcall,
    _reduceErrors
};

Production

, Comment implémenter la pagination dans Lightning Web Component &#8211; SFDCPanther<span class="wtr-time-wrap after-title"><span class="wtr-time-number">10</span> minutes de lecture</span>
Pagination dans le composant Web Lightning

Ressources

  1. https://www.thatsoftwaredude.com/content/6125/how-to-paginate-through-a-collection-in-javascript
  2. https://jasonwatmore.com/post/2018/08/07/javascript-pure-pagination-logic-in-vanilla-js-typescript
  3. https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/example

Merci d’avoir lu 🙂

En cas de doute, n’hésitez pas à me contacter.

#Salesforce #DeveloperGeeks #SFDCPanther

Cliquez pour noter cet article!

[Total:[Total:1 Moyenne: 5]



Source de l’article traduit automatiquement en Français

Besoin d'aide ?
Voulez-vous utiliser Pardot à sa capacité maximale et avoir
+ DE LEADS QUALIFIÉS

Notre analyse de votre Pardot offerte dès aujourd'hui
Merci, vous pouvez compléter notre questionnaire
Nous allons revenir vers vous rapidement !

Fermer