在 DataTable 中动态呈现列 - Column.Render 属性

Posted

技术标签:

【中文标题】在 DataTable 中动态呈现列 - Column.Render 属性【英文标题】:Dynamically Render Columns In DataTable - Column.Render Property 【发布时间】:2021-12-08 00:32:49 【问题描述】:

我正在开发一个动态数据表,其中数据源是使用 [n] 列动态生成的,其中数据源可能包含 4 列或 6 列作为示例。根据 DataTables 论坛 (How to Render Columns from a dynamic data source) 上的这篇文章,可以定义和构建列定义的变量,并将其传递给初始化。

基于此,我创建了以下代码,该代码适用于给定目的,并根据数据源动态呈现列。

html

 <div class="data-table">
        <table id="dataTable" class="table table-striped table-bordered" style="width:100%;"></table>
    </div>

脚本:

 <script>
    var dataToSend = ;
    var dataTable;

    dataToSend = 
        "regionId": @Model.RegionId
    

    // Get Column Defintions
    var dtColumns = @Html.Raw(Json.`enter code here`Serialize(listOfDefintions));

    // DataTable
    $(function () 
        dataTable = 
            dt: null,

            init: function () 
                dt = $("#dataTable").DataTable(
                    ajax: 
                        type: "GET",
                        url: "@Url.Action("GetDataForGrid", "Contact")",
                        data: function () 
                            return dataToSend;
                        ,
                        datatype: "json",
                        dataSrc: ""
                    ,
                    columns: dtColumns,
                    lengthMenu: [[10, 25, 50, 100], [10, 25, 50, 100]],
                );
            ,
            refresh: function () 
                dt.ajax.reload();
            
        

        dataTable.init();
    );

</script>

上面的代码根据下面的数据源渲染了下面的DataTable。

数据源:

渲染表:

我的问题是关于表格的最后一列空的,我需要在其中呈现一个按钮。如果我一直想渲染一个具有已知列值的表,我通常会按照下面的代码行编写一些东西,我将在其中使用 DataTable 属性 column.Render。正如您在下面看到的,使用列的 data 属性,我可以使用创建函数来呈现一个按钮,该按钮可用于快速导航到 Contact/Edit 页面,将“id”作为 Url 路由值传递,意思是可以编辑所选联系人的具体详细信息。

 <script>
    var dataToSend = ;
    var contactDataTable;

    dataToSend = 
       "regionId": @Model.RegionId
    ;

    $(function () 
        contactDataTable = 
            dt: null,

            init: function () 
                dt = $('#contact-data-table').DataTable(
                    ajax: 
                        type: "GET",
                        url: "@Url.Action("GetDataForGrid", "Contact")",
                        data: function () 
                            return dataToSend;
                        ,
                        datatype: "json",
                        dataSrc: ""
                    ,
                    columns: [
                        
                            "title": "Forename",
                            "data": "forename",
                            "searchable": true,
                        ,
                        
                            "title": "Surname",
                            "data": "surname",
                            "searchable": true,
                        ,
                        
                            "title": "Email",
                            "data": "email",
                            "searchable": true
                        ,
                        
                            "Status":
                            "status":
                            "searchable":
                        ,
                        
                            "title": "Role",
                            "data": "roleName",
                            "searchable": true
                        ,
                        
                            "title": "",
                            "data": "id",
                            "searchable": false,
                            "sortable": false,
                            "render": function (data, type, full, meta) 
                                var buffer = '<a href="@Url.Action("Edit","Contact")/' + data  + '" class="btn btn-sm btn-primary js-action"><i class="far fa-edit"></i></a>&nbsp;'

                                buffer += '<a href="@Url.Action("Delete", "Contact")/' + data + '" class="btn btn-sm btn-danger js-action"><i class="far fa-trash-alt"></i></a>';

                                return buffer;
                            
                        
                    ],
                    columnDefs: [
                         "width": "15%", "targets": 0 ,
                         "width": "15%", "targets": 1 ,
                         "width": "20%", "targets": 2 ,
                         "width": "15%", "targets": 3 ,
                         "width": "15%", "targets": 4 ,
                         "width": "20%", "targets": 5 ,
                    ],
                    lengthMenu: [[10, 25, 50, 100], [10, 25, 50, 100]],
                );
            ,
            refresh: function () 
                dt.ajax.reload();
            
        
</script>

如果我在将列定义变量传递给我的 DataTable 初始化之前定义和构建列定义变量,如何实现在表中呈现按钮的相同原理?

任何帮助都会很棒。

【问题讨论】:

对不起,我不明白......你似乎在朝着一个好的方向前进,应该可以使用数据变量来构造一个传递 id 的 URL - 那么在哪里有问题吗? 建议:不要使用dataSrc: "",而是使用函数:dataSrc: function ( json ) ... 。你可以看到一个例子here。这允许您遍历源 JSON 数据,并向每一行添加一个新对象 - 其中该对象是一个字符串,其中包含您要构建的按钮的 HTML。这相当于您想在列渲染器中使用的逻辑。 @MBaas - 在提供的示例中,我希望在表格的最后一列中呈现一个按钮,但在实际呈现 HTML 元素时遇到了困难。在我解决这个问题的各种迭代中,我要么能够呈现一个按钮,但不能访问列的数据属性,在这种情况下是 Id,反之亦然。 我已经能够同时解决这个问题,如果需要我会很乐意发布。我可以按照 andrewJames 的建议来解决这个问题,但是我发现只需将最后一列的 Data 属性设置为 null,并使用 defaultContent 来呈现一个简单的按钮效果很好。然后,我开发了一个点击事件,它获取了当前行的数据,我可以在其中访问 Id 属性以在我的 URL 的构造中使用。很可能有更好的方法,在这种情况下,我将寻求实施。 这是一个很好、直接的解决方案。欢迎您answer your own question - 如果您愿意,您也可以接受它。这将有助于未来的访问者解决这个问题。 【参考方案1】:

给定问题的简单解决方案是使用Column.defaultContent 属性和自定义onClick 事件,可用于构造所需的相关URL。

在下面的示例中,我修改了我的dtColumns 数组,如提供的图像所示,以便相关对象包含defaultContent 的定义,设置为将呈现简单按钮的字符串。要让DataTable 使用defaultContent,您必须将Data 属性设置为null。

DataTable - 数据源

var myColumnDefs = [
         title: "Forename", data: "forename", width: "15%",
         title: "Surname", data: "surname", width: "15%",
         title: "Email", data: "email", width: "20%",
         title: "Status", data: "status", width: "15%",
         title: "Role", data: "roleName", width: "15%",
         title: "", data: "(string)null", width: "20%", searchable: false, sortable: false, defaultContent: "<a id='btnEdit' class='btn btn-sm btn-primary js-action'><i class='fas fa-edit'></i></a>"
    ]

这样做会呈现如下表:

修改后的代码实际上只包含额外的函数来处理按钮的onClick 事件。在这种情况下,我可以使用$("#dataTable").DataTable().row((selectedRow).parents("tr")).data()获取加载记录的数据,其中id属性可以访问。使用这个 Id 值,我能够构建所需的 URL,该 URL 恰好被传递到呈现 Bootstrap 模式的函数中。

    <script>
    var dataToSend = ;
    var dataTable;

    // Set Data To Send
    dataToSend = 
        "regionId": "@Model.RegionId"
    

    // Get Column Defintions
    var dtColumns = @Html.Raw(Json.Serialize(listOfDefintions));

    // DataTable
    $(function () 
        dataTable = 
            dt: null,

            init: function () 
                dt = $("#dataTable").DataTable(
                    ajax: 
                        type: "GET",
                        url: "@Url.Action("GetDataForGrid", "Contact")",
                        data: function () 
                            return dataToSend;
                        ,
                        datatype: "json",
                        dataSrc: ""
                    ,
                    columns: dtColumns,
                    lengthMenu: [[10, 25, 50, 100], [10, 25, 50, 100]],
                );
            ,
            refresh: function () 
                dt.ajax.reload();
            
        

        dynaGridDataTable.init();


        // DataTable Buttons
        $("#dataTable").on("click", ".js-action", function (event) 
            var btnId = $(this).attr("id");
            var recordId = getRecordId($(this));

            if (btnId !== undefined && btnId == "btnEdit") 
                // Create Edit URL
                var href = '@Url.Action("Popup", "DynaGrid")?appGridName=@Model.AppGrid.GridName&masterRecordId=@Model.AppGrid.MasterRecordFKId&id=' + recordId + '';
                
                renderModalForDataTableButton(href);
             else if (btnId !== undefined && btnId == "btnDelete") 
                // Code 
                
             else 
                alert("Something Went Wrong - Unable To Redirect");
            
        );

        // Get Record Id Of Current Row
        function getRecordId(selectedRow) 
            var data = $("#dataTable").DataTable().row((selectedRow).parents("tr")).data();
            return data.id;
        

        function renderModalForDataTableButton(href) 
            $.get(href, function (data) 
                $('#myModalContent').html(data);
                $('#myModal').modal('show');
            );
        
    );
</script>

【讨论】:

请选择输入代码、日志等而不是截图。这使得它对许多用户来说更具可读性,并且可以被搜索引擎机器人索引。

以上是关于在 DataTable 中动态呈现列 - Column.Render 属性的主要内容,如果未能解决你的问题,请参考以下文章

DataTable 修改列名 删除列 调整列顺序

基于if条件的jQuery DataTable列

“未找到记录”不考虑有条件呈现的 p:dataTable 列

JQuery DataTable 插件宽度问题

C# ,winform把datatable导出到excel并且在列标题上面增加一行。

如何从字符串列表中的名称和类型动态创建 DataTable 列? [复制]