项目

ASP.NET Core MVC / Razor Pages: 数据表格

数据表格(又名数据网格)是一种向用户展示表格化数据的 UI 组件。市面上有很多数据表格组件/库,您可以使用任何您喜欢的与 ABP 配合使用。然而,启动模板附带了 DataTables.Net 库,并已预安装和配置。ABP 为此库提供了适配器,使其易于与 API 端点配合使用。

来自用户管理页面的示例截图,展示了在数据表格中显示的用户列表:

datatables-example

DataTables.Net 集成

首先,您可以阅读官方文档以了解 DataTables.Net 的工作原理。本节将重点介绍 ABP 的附加功能和集成点,而不是全面覆盖该库的使用。

快速示例

您可以按照 Web 应用程序开发教程 来查看一个完整的使用 DataTables.Net 作为数据表格的示例应用程序。本节展示一个极简示例。

您无需手动将 DataTables.Net 库添加到页面,因为它默认已添加到全局捆绑包中。

首先,添加一个带有 idabp-table,如下所示:

<abp-table striped-rows="true" id="BooksTable"></abp-table>

abp-table 是 ABP 定义的 标签助手,但简单的 <table...> 标签也同样有效。

然后在表格选择器上调用 DataTable 插件:

var dataTable = $('#BooksTable').DataTable(
    abp.libs.datatables.normalizeConfiguration({
        serverSide: true,
        paging: true,
        order: [[1, "asc"]],
        searching: false,
        ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList),
        columnDefs: [
            {
                title: l('Actions'),
                rowAction: {
                    items:
                        [
                            {
                                text: l('Edit'),
                                action: function (data) {
                                    ///...
                                }
                            }
                        ]
                }
            },
            {
                title: l('Name'),
                data: "name"
            },
            {
                title: l('PublishDate'),
                data: "publishDate",
                render: function (data) {
                    return luxon
                        .DateTime
                        .fromISO(data, {
                            locale: abp.localization.currentCulture.name
                        }).toLocaleString();
                }
            },
            {
                title: l('Price'),
                data: "price"
            }
        ]
    })
);

上面的示例代码使用了一些 ABP 集成功能,这些功能将在后续章节中解释。

配置标准化

abp.libs.datatables.normalizeConfiguration 函数接收一个 DataTables 配置并进行标准化以简化它;

  • 如果未设置,则将 scrollX 选项设置为 true
  • 为列定义设置 target 索引。
  • language 选项设置为使用当前语言本地化表格。

默认配置

normalizeConfiguration 使用默认配置。您可以使用 abp.libs.datatables.defaultConfigurations 对象更改默认配置。示例:

abp.libs.datatables.defaultConfigurations.scrollX = false;

以下是所有配置选项:

  • scrollX: 默认 false
  • dom: 默认值为 <"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>
  • language: 一个使用当前语言返回本地化文本的函数。

AJAX 适配器

DataTables.Net 有其自己预期的数据格式,当向服务器发起 AJAX 调用以获取表格数据时。这些格式尤其与分页和排序参数的发送和接收方式有关。ABP 也为其客户端-服务器 AJAX 通信提供了自己的约定。

abp.libs.datatables.createAjax 方法(在上面的示例中使用)适配请求和响应的数据格式,并能完美地与动态 JavaScript 客户端代理系统协同工作。

这是自动工作的,因此大多数情况下您无需了解其工作原理。如果您想了解更多关于 IPagedAndSortedResultRequestIPagedResult 以及其他在客户端与服务器通信中使用的标准接口和基础 DTO 类的信息,请参阅 DTO 文档

createAjax 还支持您自定义请求参数和处理响应。

示例:

var inputAction = function (requestData, dataTableSettings) {
    return {
        id: $('#Id').val(),
        name: $('#Name').val(),
    };
};

var responseCallback = function(result) {

    // 您的自定义代码。

    return {
        recordsTotal: result.totalCount,
        recordsFiltered: result.totalCount,
        data: result.items
    };
};

ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList, inputAction, responseCallback)

如果您不需要访问或修改 requestDatadataTableSettings,可以将一个简单的对象指定为第二个参数。

ajax: abp.libs.datatables.createAjax(
    acme.bookStore.books.book.getList, 
    { id: $('#Id').val(), name: $('#Name').val() }
)

行操作

rowAction 是 ABP 为列定义添加的一个选项,用于显示一个下拉按钮,以对表格中的某一行执行操作。

下面的示例截图显示了用户管理表中每个用户可执行的操作:

datatables-example

rowAction 作为列定义的一部分进行定义:

{
    title: l('Actions'),
    rowAction: {
        //TODO: 配置
    }
},

示例:为书籍行显示编辑删除操作

{
    title: l('Actions'),
    rowAction: {
        items:
            [
                {
                    text: l('Edit'),
                    action: function (data) {
                        //TODO: 打开模态框以编辑书籍
                    }
                },
                {
                    text: l('Delete'),
                    confirmMessage: function (data) {
                        return "确定要删除书籍 " + data.record.name + " 吗?";
                    },
                    action: function (data) {
                        acme.bookStore.books.book
                            .delete(data.record.id)
                            .then(function() {
                                abp.notify.info("删除成功!");
                                data.table.ajax.reload();
                            });
                    }
                }
            ]
    }
},

操作项

items 是一个操作定义数组。一个操作定义可以有以下选项:

  • text: 此操作在下拉菜单中显示的文本(string)。
  • action: 当用户点击操作时执行的 function。该函数接收一个 data 参数,该参数包含以下字段:
    • data.record: 这是与该行相关的数据对象。您可以访问数据字段,如 data.record.iddata.record.name 等。
    • data.table: DataTables 实例。
  • confirmMessage: 一个 function(参见上面的示例),返回一个消息(string),用于在执行 action 之前向用户显示对话框以获取确认。示例确认对话框:

datatables-row-actions-confirmation

您可以使用本地化系统来显示本地化消息。

  • visible: 一个 bool 或返回 boolfunction。如果结果为 false,则该操作不会显示在操作下拉菜单中。这通常与授权系统结合使用,如果用户没有执行此操作的权限,则隐藏该操作。示例:
visible: abp.auth.isGranted('BookStore.Books.Delete');

如果您定义一个 function,则该 function 有两个参数:record(相关行的数据对象)和 table(DataTable 实例)。因此,您可以根据行数据和其他条件动态决定显示/隐藏操作。

  • iconClass: 可用于在操作文本旁边显示字体图标,例如 Font-Awesome 图标(例如:fas fa-trash-alt)。示例截图:

datatables-row-actions-confirmation

  • enabled: 一个返回 boolfunction,用于禁用操作。该 function 接收一个具有两个字段的 data 对象:data.record 是与行相关的数据对象,data.table 是 DataTables 实例。
  • displayNameHtml: 如果 text 值包含 HTML 标签,则将其设置为 true

关于操作项有一些规则:

  • 如果没有一个操作项可见,则不会渲染操作列。

数据格式

问题

请看下面示例中的 创建时间 列:

{
    title: l('CreationTime'),
    data: "creationTime",
    render: function (data) {
        return luxon
            .DateTime
            .fromISO(data, {
                locale: abp.localization.currentCulture.name
            }).toLocaleString(luxon.DateTime.DATETIME_SHORT);
    }
}

render 是 DataTables 的一个标准选项,用于通过自定义函数渲染列内容。此示例使用 luxon 库(默认已安装)来写入 creationTime 的、符合当前用户语言习惯的人类可读值。该列的示例输出:

datatables-custom-render-date

如果您不定义 render 选项,那么结果将不美观且不用户友好:

datatables-custom-render-date

然而,渲染 DateTime 几乎是相同的,到处重复相同的渲染逻辑违反了 DRY(不要重复自己!)原则。

dataFormat 选项

dataFormat 列选项指定用于渲染列数据的数据格式。相同的输出可以使用以下列定义实现:

{
    title: l('CreationTime'),
    data: "creationTime",
    dataFormat: 'datetime'
}

dataFormat: 'datetime' 指定了此列的数据格式。有一些预定义的 dataFormat

  • boolean: 为 true 显示 check 图标,为 false 显示 times 图标,适用于渲染 bool 值。
  • date: 显示 DateTime 值的日期部分,根据当前文化进行格式化。
  • datetime: 显示 DateTime 值的日期和时间(不包括秒),根据当前文化进行格式化。

默认渲染器

abp.libs.datatables.defaultRenderers 选项允许您定义新的数据格式并为其设置渲染器。

示例:根据性别渲染男性/女性图标

abp.libs.datatables.defaultRenderers['gender'] = function(value) {
    if (value === 'f') {
        return '<i class="fa fa-venus"></i>';
    } else {
        return '<i class="fa fa-mars"></i>';
    }
};

假设某列数据的可能值为 fmgender 数据格式将显示女性/男性图标,而不是 fm 文本。现在您可以为具有适当数据值的列定义设置 dataFormat: 'gender'

您可以将默认渲染器写入一个单独的 JavaScript 文件中,并将其添加到全局脚本捆绑包,以便在所有页面中重用它们。

其他数据网格

您可以使用任何您喜欢的库。例如,参阅这篇文章以了解如何在您的应用程序中使用 DevExtreme 数据网格。

在本文档中