首页 > 解决方案 > 仅按字符串的某些部分对表格进行排序

问题描述

使用分拣机进行分拣基本上可以正常工作。一栏是全名(例如“Steve Jobs”)。我在该实体集中只有全名,但我想在单击全名列标题时按姓氏(全名的最后一个单词)对条目进行排序。有没有办法做到这一点?

标签: sapui5

解决方案


您需要为排序器定义一个自定义比较器,该比较器仅适用于所有实体在客户端可用的情况,例如,通过在定义 OData 列表绑定时operationMode设置为。API'Client'

sap.ui.getCore().attachInit(() => sap.ui.require([
  "sap/ui/model/odata/v2/ODataModel",
  "sap/ui/core/mvc/XMLView",
  "sap/ui/model/json/JSONModel",
  "sap/ui/model/Sorter",
], (ODataModel, XMLView, JSONModel, Sorter) => {
  "use strict";
  const odataModel = new ODataModel({
    serviceUrl: [
      "https://cors-anywhere.herokuapp.com/",
      "https://services.odata.org/V2/Northwind/Northwind.svc/",
    ].join(""),
    tokenHandling: false,
    preliminaryContext: true,
  });
  Promise.all([
    odataModel.metadataLoaded(),
    sap.ui.getCore().loadLibrary("sap.m", true),
  ]).then(() => XMLView.create({
    definition: `<mvc:View xmlns:mvc="sap.ui.core.mvc"
      xmlns="sap.m"
      xmlns:core="sap.ui.core"
      height="100%"
    >
      <App>
        <Page showHeader="false">
          <Table id="myResponsiveTable"
            items="{
              path: '/Customers',
              parameters: {
                select: 'CustomerID, ContactName',
                operationMode: 'Client'
              }
            }"
          >
            <columns>
              <Column id="customerIdColumn"
                sortIndicator="{colCustomerId>/sortOrder}"
                width="33%"
              >
                <Text text="Customer ID">
                  <customData>
                    <core:CustomData
                      key="sorterPath"
                      value="CustomerID"
                    />
                  </customData>
                </Text>
              </Column>
              <Column id="fullNameColumn"
                sortIndicator="{colFullName>/sortOrder}"
                width="auto"
              >
                <Text text="Full Name">
                  <customData>
                    <core:CustomData
                      key="sorterPath"
                      value="ContactName"
                    />
                  </customData>
                </Text>
              </Column>
            </columns>
            <ColumnListItem>
              <Text text="{CustomerID}" />
              <Text text="{ContactName}" />
            </ColumnListItem>
          </Table>
        </Page>
      </App>
    </mvc:View>`,
    afterInit: function() { // === onInit
      const table = this.byId("myResponsiveTable");
      activateColumnPress(table, onColumnPress);
    },
    models: {
      undefined: odataModel,
      colCustomerId: new JSONModel({ sortOrder: "None" }),
      colFullName: new JSONModel({ sortOrder: "None" }),
    }
  }).then(view => view.placeAt("content")));

  function activateColumnPress(table, handler) {
    // Making columns clickable for the demo
    table.bActiveHeaders = true;
    table.onColumnPress = col => handler(table, col);
  }
  
  function onColumnPress(table, pressedCol) {
    table.getColumns()
      .filter(col => !(col.getSortIndicator() === pressedCol.getSortIndicator()))
      .map(col => col.setSortIndicator("None"));
    table.getBinding("items").sort(createSorter(pressedCol));
  }

  function createSorter(column) {
    return column.getHeader().data("sorterPath") === "ContactName"
      ? createFullNameSorter(column, toggleSort(column.getModel("colFullName")))
      : createCustomerIdSorter(column, toggleSort(column.getModel("colCustomerId")));
  }

  function toggleSort(colModel) {
    const descending = colModel.getProperty("/sortOrder") !== "Ascending";
    colModel.setProperty("/sortOrder", descending ? "Ascending" : "Descending");
    return !descending;
  }

  function createFullNameSorter(column, descending) {
    const comparator = (a, b) => a.split(" ").pop().localeCompare(b.split(" ").pop());
    return new Sorter("ContactName", descending, false, comparator);
  }

  function createCustomerIdSorter(column, descending) {
    return new Sorter("CustomerID", descending);
  }

}));
<script id="sap-ui-bootstrap"
  src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
  data-sap-ui-libs="sap.ui.core"
  data-sap-ui-async="true"
  data-sap-ui-compatversion="edge"
  data-sap-ui-theme="sap_belize"
  data-sap-ui-xx-waitfortheme="true"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact" style="height: 100%;"></body>

顺便说一句:如果服务实现了服务器端分页,则“客户端”操作模式当前不会获取所有实体

正如您在上面的示例中所见,Sorter构造函数可以处理将在调用sort方法时调用的自定义比较器。为了比较全名的最后部分,您可以像这样定义比较器:

function compare(fullName_a, fullName_b) {
  const lastPart_a = fullName_a.split(" ").pop();
  const lastPart_b = fullName_b.split(" ").pop();
  return lastPart_a.localeCompare(lastPart_b); // 0 if equal. Otherwise a negative or positive number
}

推荐阅读