Kendo UI Grid 批量編輯使用總結


項目中使用Kendo UI Grid控件實現批量編輯,現在將用到的功能總結一下。

批量編輯基本設置

Kendo Grid的設置方法如下:

                    $("#grid").kendoGrid({
                        toolbar: ["create","save", "cancel"],
                         columns: [
                            { field: "OBJECTID", title: "ID" },
                            ...
                        ],
                        dataSource: {
                            transport: {
                                read: {
                                    url: myRoot + "GetPagedData"
                                },
                                update: {
                                    url: myRoot + "UpdateBatch"
                                },
                                create: {
                                    url: myRoot + "UpdateBatch"
                                },
                                delete:{
                                    url:myRoot+"DeleteDate"
                                }
                            },
                            pageSize: 100,
                            serverPaging: true,
                            serverSorting: true,
                            schema: {
                                total: "rowCount", 
                                data: "Rows",
                                model: {
                                    id: "OBJECTID",
                                    fields: {
                                        OBJECTID: { editable: false, nullable: true },
                                        NAME: { editable: true, validation: { required: true } },
                                        ...
                                    }
                                }
                            },
                            batch: true,  
                        },
                        pageable: {
                            pageSize: 10
                        },
                        height: "600px",
                        editable: true
                    });

  • toolbar:創建網格中的按鈕,這里創建“新增”、“保存”和“取消”。
  • columns:在網格中顯示的列,這是一個數組,每一列可以定義字段的名稱,顯示的文本,顯示的模板和自定義的編輯器
  • dataSource:定義了與網格相關的kendo dataSource對象。在transport中定義了進行CRUD的對象(或者函數),如果批量修改,需要在dataSource中將batch設置為true。如果批量修改,還需要在schema中設置model,包括id和各個字段的定義。
  • editable屬性需要設置為true。

基本設置完成后,網格就可以進行批量編輯了,點擊網格中的單元格,會加載動態文本框,進行編輯,編輯完成后,改變值的網格會有變化提示。

Grid批量編輯中的下拉框設置

在前面的例子中,網格中顯示人員所在的部門,我們在編輯時,需要使用下拉框選擇所在的部門:

這里需要解決幾個問題:
1、我們在數據庫中保存的是部門的id,不是部門的名稱,而在顯示時,需要顯示部門的名稱。
2、在編輯時,我們需要加載下拉框,並獲取部門的數據,進行編輯。

為了解決第一個問題,我們在返回的數據中,不僅返回部門的id,還返回部門的名稱,

                        model: {
                                    id: "OBJECTID",
                                    fields: {
                                        ...
                                        DEPARTMENTID: { editable: true, },
                                        DEPARTMENTID_DicText: { editable: false, nullable: true  },
                                        ...
                                    }
                                }

在模型定義中,定義DEPARTMENTID為可編輯的,DEPARTMENTID_DicText不可編輯。
在columns的定義中,定義DEPARTMENTID的顯示模板為DEPARTMENTID_DicText:

 { field: "DEPARTMENTID", title: "部門", editor: categoryDropDownEditor, template: "#=DEPARTMENTID_DicText#" },

這樣DEPARTMENTID在網格顯示時,實際顯示的是DEPARTMENTID_DicText

為了實現下拉框選擇,我們創建自定義的編輯器,categoryDropDownEditor,這個編輯器是一個函數:

                //自定義編輯控件,下拉框
                function categoryDropDownEditor(container, options) {
                    $('<input  name="' + options.field + '"/>')
                        .appendTo(container)
                        .kendoDropDownList({
                            autoBind: false,
                            dataTextField: "Text",
                            dataValueField: "Value",
                            height: 600,
                            dataSource: {
                                transport: {
                                    read: {
                                        url: myRoot + "GetDictionary"
                                    }
                                }
                            },
                            change: function (e) {
                                options.model[options.field + "_DicText"] = e.sender.text();
                            }
                        });
                }

這個函數中創建了一個input控件,並轉換為kendoDropDownList下拉框,下拉框通過ajax獲取部門的數據,選擇后,修改模型中保存的數據。

Grid批量編輯中的日期編輯器設置

前面我們討論了在Kendo UI Grid中下拉框的設置,這里討論如何設置日期編輯器。

自定義日期編輯器

在上面的例子中,有入職日期字段,需要使用日期選擇器進行編輯,由於kendo的日期型在服務器端不容易轉換,所有我們采用字符串進行傳輸,因此在模型中,我們沒有將這個字段定義為日期型,而是保持為字符型:

                                model: {
                                    id: "OBJECTID",
                                    fields: {
                                        ...
                                        JOINDATE: { editable: true, format: "yyyy-MM-dd", type: "string" },
                                        ...
                                    }
                                }

在columns中:

                        columns: [
                            ...
                            { field: "JOINDATE", title: "入職日期", editor: dateEditor },
                            ...
                        ],

在這里,我們定義了這個列的自定義編輯器,是一個函數,自定義的日期編輯器函數如下:

                //自定義編輯控件,日期
                function dateEditor(container, options) {
                    $('<input  name="' + options.field + '"/>')
                        .appendTo(container)
                        .kendoDatePicker(
                            {
                            format: "yyyy-MM-dd",
                            culture: "zh-CN",
                                change: function (e) {
                                    options.model[options.field] = kendo.toString(e.sender.value(), "yyyy-MM-dd");
                                }
                            })
                }

在這個函數里,創建一個input標簽,並轉換為kendo DatePicker,在change事件中改變模型中的值。這樣就完成了網格單元格編輯的日期編輯器。

Grid批量編輯中的Checkbox編輯器設置

我們需要在網格中用checkbox顯示ISFULLTIME,如果值為1,顯示選中,如果為0,顯示沒有選中。可以通過創建模板的方式實現。模板代碼如下:

 { template: '#=dirtyField(data,"ISFULLTIME")#<input type="checkbox" #=ISFULLTIME== 1 ? \'checked="checked"\' : "" # class="chkbx" ref="ISFULLTIME" />', width: 110 },

我們在change事件中響應選擇動作,改變模型中相應的值。

 $("#grid .k-grid-content").on("change", "input.chkbx", function (e) {
                        var field = $(this).attr("ref")
                        var grid = $("#grid").data("kendoGrid"),
                        dataItem = grid.dataItem($(e.target).closest("tr"));

                        dataItem.set(field, this.checked ? 1 : 0);
                    });

我們還需要處理臟數據,也就是正在編輯的數據,如果數據發生了改變,則在網格中進行標識。這個函數的代碼如下:

function dirtyField(data, fieldName) {
                        var hasClass = $("[data-uid=" + data.uid + "]").find(".k-dirty-cell").length < 1;
                        if (data.dirty && data[fieldName]!=data[fieldName+"_DICTEXT"] && hasClass) {
                            return "<span class='k-dirty'></span>"
                        }
                        else {
                            return "";
                        }
                    }

Grid批量編輯中的Checkbox編輯器另一種方法

在這個例子中,有一個是否全職的字段,ISFULLTIME,這個字段是數值型,用1和0表示true和false,在編輯時,我們希望使用checkbox進行編輯,但希望獲得的值是1和0,而不是true和false。
在model中的定義這個字段和一個附加字段,用於編輯:

                               model: {
                                    id: "OBJECTID",
                                    fields: {
                                        ...
                                        ISFULLTIME: { editable: true },
                                        ISFULLTIME_DICTEXT: { editable: true}
                                    }

在columns中的定義,注意這里我們編輯的是ISFULLTIME_DICTEXT:

                        columns: [
                            ...
                            { field: "ISFULLTIME_DICTEXT", title: "是否全職", editor: customBoolEditor, template: "#=GetFullTime(ISFULLTIME)#" },
                        ],

這里我們希望顯示“是”和“否”,因此模板調用了轉換函數:

               function GetFullTime(va) {
                    if (va == 1) return "是";
                    return "否";
                }

自定義的編輯器如下:


                //自定義編輯控件,checkbox
                function customBoolEditor(container, options) {
                    var guid = kendo.guid();
                    $('<input class="k-checkbox" id="' + guid + '" type="checkbox" name="' + options.field + '" data-type="boolean" data-bind="checked:' + options.field + '">').appendTo(container)
                        .on("click", function (e) {
                            var field = options.field.replace("_DICTEXT", "");
                            if (e.target.checked)
                                options.model[field] = 1;
                            else
                                options.model[field] = 0;
                        });
                    $('<label class="k-checkbox-label" for="' + guid + '">&#8203;</label>').appendTo(container);
                }

這里,在控件值改變時,將模型相關的值改變為1或0。

在網格之外添加“新增”、“保存”和“取消”

在網格中增加“新增”、“保存”和“取消”很容易,只要在網格定義中增加toolbar: ["create","save", "cancel"]就可以了。但在某些情況下,我們希望在網格之外增加這些功能按鈕,並通過調用Api實現相應的功能。

如果我們希望在網格之外添加這幾個按鈕,可以直接調用dataSource的相關api:
html代碼:

        <span id="btnAdd" class="btn btn-default">新增</span>
        <span id="btnSave" class="btn btn-default">保存</span>
        <span id="btnCancel" class="btn btn-default">取消修改</span>

相關的JS代碼如下:

                    //增加保存按鈕
                    $("#btnSave").bind("click", function () {
                        var grid = $("#grid").data("kendoGrid");
                        grid.dataSource.sync();;
                    });

                    //增加取消按鈕
                    $("#btnCancel").bind("click", function () {
                        var grid = $("#grid").data("kendoGrid");
                        grid.dataSource.cancelChanges();
                    });

                    //增加添加按鈕
                    $("#btnAdd").bind("click", function () {
                        var grid = $("#grid").data("kendoGrid");
                        grid.dataSource.add();
                    });

這些按鈕執行效果與網格中toolbar定義的按鈕效果相同。

為Kendo Grid 增加自定義統計行

Kendo Grid支持增加列統計的功能,對某一列的數據在底部顯示合計值、平均值等等。但這些功能都是在客戶端進行的,如果數據量很大,需要在服務端進行分頁處理等,就不能使用這些客戶端的功能,而是需要在服務端進行計算,然后在網格中顯示。為了實現這種需求,我們需要:

  • 在服務端增加計算統計值的Api
  • 在客戶端調用這個Api,使用自定義模板顯示

這里假設我們已經有了在服務計算統計值的Api,主要說明如何在客戶端顯示這些計算值。

首先,需要增加保存統計值的對象:

var agData = {};//保存從服務器Api獲取的統計數據

然后,在grid的列定義中增加footerTemplate,比如:

 { field: "AGE", title: "年齡", width: "500px", footerTemplate:"<span id='footerAGE'>#=getAgData('AGE')#</span>"},

在模板里,我們使用一個函數獲取統計值,獲取函數如下:

function getAgData(field) {
    if (agData[field]) return agData[field];
    return "";
}

在查詢函數中調用服務端的Api,獲取統計數據,並將統計數據保存到agData:

         function doSearch() {
            //網格查詢部分略

            //這里通過自定義的Api查詢統計數據,postdata中包含查詢條件
             MyApi.getSumData(postdata, function (res) {
                 agData = res;
                 });

         }

Grid保持行展開狀態

在使用Kendo UI Grid時,如果重新綁定,也就是當dataBound事件被觸發時,原來展開的行會收起,如果希望保持行的展開狀態,需要在行展開時,記錄展開行的id,然后在重新綁定時,回復展開的狀態。我們可以將展開行的id保持在本地存儲中。下面的例子是使用MVVM下的代碼:

 <div id="dsgrid" class="grid"
                         data-role="grid"
                         data-sortable="true"
                         data-toolbar="['create']"
                         data-detail-init="viewModel.dsgrid_detailInit"
                         data-bind="source: dsSource, events: { dataBound: ds_dataBound,detailExpand:ds_DetailExpand, detailCollapse:ds_DetailCollapse }"
                         data-editable='{"mode": "popup" }'
                         data-columns='[
                                 {"field":"Name","title":"名稱"},
                                 {"field":"Title","title":"說明"},
                                 {"field":"TableName","title":"數據庫數據源表名稱"},
                                  {"field":"GetDataUrl","title":"Api數據源Url"},
                                 {"field":"TextField","title":"文本字段"},
                                 {"field":"ValueField","title":"值字段"},
                                 {"command": [ "edit", "destroy" ], "filterable": false, "sortable": false, "width:": "240px"}
                                 ]'
                         data-detail-template='dssubgrid'
                         data-scrollable="false">
                    </div>

代碼中聲明了三個事件,dataBound,detailExpand和detailCollapse,在detailExpand事件中,記錄下展開行對應的數據id:

ds_DetailExpand: function (e) {
                    var grid = $("#dsgrid").data("kendoGrid");
                    var item = grid.dataItem(e.masterRow);
                    var items = localStorage['expanded'];
                    if (items) {
                        items = JSON.parse(items);
                    } else {
                        items = [];
                    }
                    items.push(item.Name);
                    localStorage['expanded'] = JSON.stringify(items);
                },

在detailCollapse事件中,將該行記錄的id去掉:

                ds_DetailCollapse: function (e) {
                    var grid = $("#dsgrid").data("kendoGrid");
                    var item = grid.dataItem(e.masterRow);
                    var items = JSON.parse(localStorage['expanded']);

                    items = items.filter(function (x) {
                        return x != item.Name;
                    });

                    localStorage['expanded'] = JSON.stringify(items);
                },

在dataBound事件中,展開對應的行:

               ds_dataBound: function (e) {
                    var row = e.sender.tbody.find("tr.k-master-row").first();
                    var items = localStorage['expanded'];
                    var grid = $("#dsgrid").data("kendoGrid");
                    if (items) {
                        items = JSON.parse(items);
                        items.forEach(function (x) {
                            var item = grid.dataSource.view().find(function (y) {
                                return y.Name == x;
                            });
                            if (item) {
                                row = $('#' + grid.element.attr('id') + ' tr[data-uid="' + item.uid + '"]')
                            } 
                        })
                    } 
                    e.sender.expandRow(row);
                    
                },


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM