Кастомная сортировка в Lightning

В данной статье рассмотрим, как можно реализовать кастомную сортировку таблицы в Lightning. Так как таблицу в Lightning можно построить разными способами, то дальше рассмотрим сортировку для таблицы, построенной с помощью HTML тега “table” и Lightning тега “lightning:datatable”.

Какую реализацию таблицы использовать — решайте сами ниже просто опишу их возможности.

HTML таблица “table” - это просто html таблица к которой можно применять CSS стили Lightning Design System. Можно кастомизировать, как хотите. Какой-то дополнительный функционал нужно реализовывать самому.

Lightning таблица “lightning:datatable” - это lightning aura тег, который позволяет построить таблицу с уже реализованными функциями. Что поддерживает тег:

  • Отображение и форматирование столбцов с соответствующими типами данных;
  • Прокрутка строк;
  • Возможность редактирования значения в строке (применимо не для всех типов);
  • Можно добавить actions на заглавие или строку таблицы;
  • Изменение размера столбцов;
  • Выбор строк. Можно включить checkbox;
  • Нумерация строк;
  • Выравнивание содержимого ячейки.

Но эта таблица не поддерживается в мобильной версии.
Вот ссылка на полное описание из документации:
https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/documentation

Итак, сначала рассмотрим сортировку для HTML таблицы:

1. Lightning компонент

<aura:component description="TestListForm" controller="FormTestController">
    <aura:attribute name="accounts" type="List"/>
    <aura:attribute name="sortDirection" type="Boolean" default="true"/>
    <aura:attribute name="arrow" type="String" default="utility:arrowup"/>
    <lightning:overlayLibrary aura:id="overlayLibDemo"/>

    <div class="slds-card slds-p-top--medium">
        <header class="slds-card__header">
            <h3 class="slds-text-heading--small">Accounts</h3>
        </header>

        <section class="slds-card__body">
            <div id="list" class="row">


                <table class="slds-table slds-table_cell-buffer slds-table_bordered">
                    <thead>
                    <tr class="slds-line-height_reset">
                        <th class="slds-text-title_caps" scope="col">
                            <div class="slds-truncate" title="Accoint Id">Accoint Id</div>
                        </th>
                        <th class="slds-text-title_caps" scope="col">
                            <div class="slds-truncate" title="Account Name">Name
                                <lightning:buttonIcon onclick="{!c.sortByName}" iconName="{!v.arrow}" size="x-small" alternativeText="Order"/>
                            </div>
                        </th>
                    </tr>
                    </thead>

                    <tbody>
                    <aura:iteration items="{!v.accounts}" var="acc">
                    <tr class="slds-hint-parent">
                        <td data-label="Accoint Id">
                            <div class="slds-truncate" title="Accoint Id">{!acc.Id}</div>
                        </td>
                        <td data-label="Accoint Name">
                            <div class="slds-truncate" title="Accoint Name">{!acc.Name}</div>
                        </td>
                    </tr>
                    </aura:iteration>
                    </tbody>
                </table>
            </div>
        </section>
    </div>
    <lightning:button onclick="{!c.getAccounts}" label="Update"/>

</aura:component>

Это разметка HTML таблицы с применением Salesforce Lightning стилей, где в имя столбца, которым можно сортировать, я вставил тег “lightning:buttonIcon” - это стандартная иконка стрелочки для сортировки.

По нажатию на эту стрелочку будет производится сортировка с помощью вызова JavaScript метода lightning:buttonIcon onclick="{!c.sortByName}".

В атрибут тега iconName="{!v.arrow}" подставляем переменную “arrow” определенную в начале <aura:attribute name="arrow" type="String" default="utility:arrowup"/>.

У этой переменной по дефолту default="utility:arrowup" указано имя иконки “utility:arrowup”. Это значение мы буде менять на “utility:arrowdown” и обратно в JavaScript методе при нажатии на иконку.

Переменная <aura:attribute name=“sortDirection” type=“Boolean” default=“true”/> служит для указания направления сортировки. Изменяется также в JavaScript методе при нажатии на иконку.

2. JavaScript контроллер

({
    getAccounts : function(component, event) {
        var action = component.get("c.getListAccounts");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.accounts", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    },

    sortByName : function (component, event) {
        var listAccs = component.get("v.accounts");
        var sortDirection = component.get("v.sortDirection");
        if (sortDirection == true) {
            listAccs.sort(function (a, b) {
                var nameA = a.Name.toLowerCase();
                var nameB = b.Name.toLowerCase();
                if (nameA < nameB) {
                    return -1;
                }
                if (nameA > nameB) {
                    return 1;
                }
                return 0;

            });
            component.set("v.sortDirection", false);
            component.set("v.arrow", "utility:arrowdown");
        }else {
            listAccs.sort(function (a, b) {
                var nameA = a.Name.toLowerCase();
                var nameB = b.Name.toLowerCase();
                if (nameB < nameA) {
                    return -1;
                }
                if (nameB > nameA) {
                    return 1;
                }
                return 0;

            });
            component.set("v.sortDirection", true);
            component.set("v.arrow", "utility:arrowup");
        }
        component.set("v.accounts", listAccs);
    }


})

В контроллере функция “sortByName” берет список Accounts - var listAccs = component.get("v.accounts"); и сортирует, при этом при каждой сортировке устанавливается правильное значение в переменные “v.arrow” и “v.sortDirection” вот таким способом:

            component.set("v.sortDirection", false);
            component.set("v.arrow", "utility:arrowdown");

А дальше отсортированный список возвращается назад на страницу:

component.set("v.accounts", listAccs)

Сортировка с использованием “lightning:datatable”.

1. Lightning компонент.

<aura:component description="TestDataTable" controller="FormTestController" implements="force:appHostable,flexipage:availableForAllPageTypes">
    <aura:attribute name="accountColumns" type="List"/>
    <aura:attribute name="accountData" type="Object"/>
    <aura:attribute name="sortBy" type="String"/>
    <aura:attribute name="sortDirection" type="String"/>
    <aura:handler name="init" action="{!c.onInit}" value="{!this}"/>
    <lightning:datatable aura:id="accountTable"
                         keyField="Id"
                         hideCheckboxColumn="true"
                         columns="{!v.accountColumns}"
                         data="{!v.accountData}"
                         sortedBy="{!v.sortBy}"
                         sortedDirection="{!v.sortDirection}"
                         onsort="{!c.handleSort}"/>
    <lightning:button onclick="{!c.getAccounts}" label="Update"/>
</aura:component>

Подробно про “lightning:datatable” можно почитать в документации вот ссылка:
https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/example
Пройдем только по основным моментам.
Аттрибут “accountColumns” - это имена колонок таблицы, которыe задаются в javaScript контроллере.

Аттрибут “accountData” - это список Accounts, который будет отображаться в таблице; задается в javaScript контроллере.

Аттрибут "sortBy" - имя столбца, по котором производится сортировка;
устанавливается автоматически тегом “lightning:datatable” вот в этом месте sortedBy="{!v.sortBy}".

Аттрибут “sortDirection” - устанавливает направление сортировки; может быть “asc” или “desc”. Устанавливается автоматически тегом “lightning:datatable” вот в этом месте sortedDirection="{!v.sortDirection}".

Тег "aura:handler " - используется для инициализации имен столбцов таблицы JavaScript контроллером. В теге вызывается метод контроллера action="{!c.onInit}", который устанавливает значения в аттрибут “accountColumns”.

2. JavaScript контроллер

({
    onInit : function(component,event,helper) {
        component.set("v.accountColumns", [
            {
                label: 'Id Account',
                fieldName: 'Id',
                type: 'text',
                sortable: false
            },
            {
                label: 'Account Name',
                fieldName: 'Name',
                type: 'text',
                sortable: true
            }
          ]);
    },

    getAccounts : function(component, event) {
        var action = component.get("c.getListAccounts");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.accountData", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    },

    handleSort : function(component,event,helper) {
        var sortBy = event.getParam("fieldName");
        var sortDirection = event.getParam("sortDirection");
        var listAccs = component.get("v.accountData");
        component.set("v.sortBy", sortBy);
        component.set("v.sortDirection", sortDirection);
        if (sortBy == "Name" && sortDirection == "asc") {
            listAccs.sort(function (a, b) {
                var nameA = a.Name.toLowerCase();
                var nameB = b.Name.toLowerCase();
                if (nameA < nameB) {
                    return -1;
                }
                if (nameA > nameB) {
                    return 1;
                }
                return 0;

            });
        } else {
            listAccs.sort(function (a, b) {
                var nameA = a.Name.toLowerCase();
                var nameB = b.Name.toLowerCase();
                if (nameB < nameA) {
                    return -1;
                }
                if (nameB > nameA) {
                    return 1;
                }
                return 0;

            });
        }
        component.set("v.accountData", listAccs);
    }
})

В функции “onInit” задаются имена столбцов и их свойство. Тут можно увидеть, что только один столбец можно отсортировать у него задано свойство “sortable: true”.

В функции “handleSort” выполняется сортировка. В нутри функции мы проверяем, что переданный для сортировки столбец это именно столбец с именнем “Name” и направление сортировки if (sortBy == "Name" && sortDirection == "asc").

Но нужно помнить, что приведенная реализация сортировки в JavaScript контроллере работает только для строковых типов данных. Если нужно сортировать другие типы данных — вам нужно реализовать сортировку для них отдельно.