Kendo UI Grid控制元件的功能強大,這裡將常用的一些功能總結一下。
Kendo UI Grid 固定列
在使用Gird控制元件顯示資料時,如果資料列過多,會出現橫向滾動條,很多情況下,我們希望某些列固定,這些列固定顯示,不隨滾動條發生變化。這時,可以在資料列上使用locked屬性,比如,下面是使用mvvm定義grid的示例,編輯按鈕被設定為固定列:
<div id="fieldgrid" class="grid"
data-role="grid"
data-sortable="true"
data-height="580"
data-toolbar="['create']"
data-bind="source: fieldSource"
data-editable='{"mode": "popup" }'
data-columns='[
{"field":"Name","title":"欄位名稱", "width": "120px"},
{"field":"Title","title":"欄位說明", "width": "120px"},
{"field":"DataType","title":"欄位型別","values":dsDataType, "width": "120px"},
{"field":"ControlType","title":"控制元件型別", "values":dsControlType, "width": "120px"},
{"field":"DefaultValue","title":"預設值", "width": "120px"},
{"field":"Editable","title":"是否可編輯", "width": "80px"},
{"field":"Visible","title":"是否可見", "width": "80px"},
{"field":"DisplayOrder","title":"顯示順序", editor: numberEditor, "width": "80px"},
{"field":"IsCascade","title":"是否級聯", "width": "80px"},
{"field":"CascadeSubField","title":"級聯下級", "width": "120px"},
{"field":"CascadeParentField","title":"級聯上級", "width": "120px"},
{"command": [ "edit", "destroy" ], "width": "180px","locked":"true"}
]'
data-scrollable="true">
需要注意的是,1)固定列總是顯示在最左邊,2)帶有固定列網格在初始化過程時,必須是可見的。如果網格在初始化時不可以見,會出現不可預知的問題。比如這種的場景,如果網格在分頁中,初始化時是不可見的,那麼,介面可能是這樣的:
Grid控制元件建立自定義彈出編輯窗
Kendo UI Grid控制元件自帶彈出窗編輯,只要在資料來源中定義schema,就可以自動生成編輯介面,程式碼如下:
<div class="form container" id="divForm">
<div id="divGrid">
<div id="mygrid" class="grid"
data-role="grid"
data-sortable="true"
data-toolbar="['create']"
data-bind="source: dataSource"
data-editable='{"mode": "popup" }'
data-columns='[
{"field":"Id","title":"ID"},
{"field":"Name","title":"姓名"},
{"field":"Age","title":"年齡"},
{"field":"JoinDate","title":"入職日期","format": "{0:yyyy-MM-dd}"},
{"field":"Sex","title":"性別","template": "#if (Sex==1){# 女 #}else{# 男 #}# "},
{"field":"Married","title":"婚姻狀況","template": "#if (Married){# 已婚 #}else{# 未婚 #}# "},
{"command": [ "edit", "destroy" ], "filterable": false, "sortable": false, "width:": "240px"}
]'
data-scrollable="false">
</div>
</div>
</div>
<script>
$(document).ready(function () {
var viewModel = kendo.observable({
dsSex: [{ value: 0, text: '男' }, { value: 1, text: '女' }],
dataSource: new kendo.data.DataSource(
{
data: [],
schema: {
model: {
id: "Id",
fields: {
Id: { editable: true, nullable: false },
Name: { validation: { required: true } },
Age: { type: "number" },
Sex: { editable: true },
JoinDate: { type: "date", editable: true },
Married: { type: "boolean", editable: true }
}
}
}
})
});
kendo.bind($("#divForm"), viewModel);
});
</script>
自動生成的編輯介面對於基本資料型別的欄位夠用了,但在實際中,會有更復雜的要求,比如,某些欄位需要使用下拉框或者更復雜的控制元件,或者我們希望欄位多列排列,這時,需要用到自定義的模板,上面的網格的自定義編輯模板如下:
<script id="popup_editor" type="text/x-kendo-template">
<div class="form container">
<div class="form-group row">
<label class="col-sm-2 control-label" for="Id">ID</label>
<div class="col-sm-4">
<input type='number' class='k-textbox' data-bind="value: Id" />
<span class="k-invalid-msg" data-for="Id"></span>
</div>
<!--</div>
<div class="form-group row">-->
<label class="col-sm-2" for="Name">姓名</label>
<div class="col-sm-4 ">
<input type='text' name="Name" class='k-input k-textbox k-valid' data-bind="value: Name" required="required" />
<span class="k-invalid-msg" data-for="Name"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="Age">年齡</label>
<div class="col-sm-4">
<input type='number' style="" data-role="numerictextbox" class='form-control' data-bind="value: Age" />
<span class="k-invalid-msg" data-for="Age"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="val_JoinDate">參加日期</label>
<div class="col-sm-4">
<input data-role="datepicker" data-culture="zh-CN" style="" class='form-control' data-bind="value: JoinDate," />
<span class="k-invalid-msg" data-for="JoinDate"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="val_Married">已婚</label>
<div class="col-sm-4">
<input type="checkbox" style="" data-bind="checked: Married," />
<span class="k-invalid-msg" data-for="Married"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="val_Sex">性別</label>
<div class="col-sm-4">
<select data-role="dropdownlist" class='form-control' data-text-field="text"
data-value-field="value" data-bind="source:dsSex,value: Sex">
</select>
<span class="k-invalid-msg" data-for="Sex"></span>
</div>
</div>
</div>
</script>
模板使用script標記,型別為text/x-kendo-template,說明是kendo的模板。模板語言就是html,其中的data標記與kendo MVVM一致。模板中有幾點需要注意:
- 模板中需要驗證的欄位,需要定義name屬性,如果不定義,驗證資訊無法顯示
- 需要定義 用於顯示驗證資訊
- 如果需要多列顯示,需要在頁面中定義自定義的樣式:
<style>
.k-edit-form-container {
width: 700px;
}
.k-edit-form-container div {
box-sizing: border-box;
}
.k-edit-form-container label {
box-sizing: border-box;
}
</style>
需要將相關元素的box-sizing 設定為border-box
為Grid建立詳細顯示資訊
KendoUI Grid支援在網格行中顯示該行資料的詳細資訊,示例介面如下:
詳細資訊部分是在Grid控制元件的detailInit事件中建立的,如果採用mvvm方式定義,示例程式碼如下:
<div id="functiongrid" class="grid"
data-role="grid"
data-sortable="true"
data-toolbar="['create']"
data-bind="source: functionSource, events: { dataBound: fn_dataBound }"
data-editable='{"mode": "popup" }'
data-detail-init="viewModel.functiongrid_detailInit"
data-detail-template='functiongridsubtemp'
data-columns='[
{"field":"FunctionName","title":"名稱"},
{"field":"Desc","title":"說明"},
{"field":"ExecuteUrl","title":"地址"},
{"field":"ViewName","title":"函式型別名"},
{"command": [ "edit", "destroy" ], "filterable": false, "sortable": false, "width:": "240px"}
]'
data-scrollable="false"
>
</div>
上面的程式碼中,detailInit事件需要寫為mvvm的方式,也就是需要用data開頭,不同的單詞中間用“-”分隔,全部為小寫,這樣,detailInit就需要寫為data-detail-init。這個事件定義的函式在檢視模型中,還有一個需要定義的屬性是detailTemplate,用於定義顯示模板,相關部分的程式碼如下:
functiongrid_detailInit: function (e) {
e.detailRow.find(".functionTab").kendoTabStrip(
{
animation: {
open: {
effects: "fadeIn"
}
}
}
);
if (!e.data.InParas) e.data.InParas = [];
if (!e.data.OutParas) e.data.OutParas = [];
if (!e.data.ExProps) e.data.ExProps = [];
var dsIn = new kendo.data.DataSource({
data: e.data.InParas,
schema: {
model: {
id: "FieldName",
fields: {
FieldName: { editable: true, validation: { required: true } },
ParaName: { editable: true, validation: { required: true } }
}
}
}
});
e.detailRow.find(".inparagrid").kendoGrid({
dataSource: dsIn,
editable: "popup",
toolbar: ['create'],
columns: [{
title: "欄位名稱",
field: "FieldName"
}, {
title: "Api引數名",
field: "ParaName"
}, {
command: ["edit", "destroy"]
}
]
});
var dsOut = new kendo.data.DataSource({
data: e.data.OutParas,
schema: {
model: {
id: "FieldName",
fields: {
FieldName: { editable: true, validation: { required: true } },
ParaName: { editable: true, validation: { required: true } }
}
}
}
});
e.detailRow.find(".outparagrid").kendoGrid({
dataSource: dsOut,
editable: "popup",
toolbar: ['create'],
columns: [{
title: "欄位名稱",
field: "FieldName"
}, {
title: "Api引數名",
field: "ParaName"
}, {
command: ["edit", "destroy"]
}
]
});
var dsEx = new kendo.data.DataSource({
data: e.data.ExProps,
schema: {
model: {
id: "PropName",
fields: {
PropName: { editable: true, validation: { required: true } },
PropValue: { editable: true, validation: { required: true } }
}
}
}
});
e.detailRow.find(".expropgrid").kendoGrid({
dataSource: dsEx,
editable: "popup",
toolbar: ['create'],
columns: [{
title: "屬性名稱",
field: "PropName"
}, {
title: "屬性值",
field: "PropValue"
}, {
command: ["edit", "destroy"]
}
]
});
},
還要定義繫結函式如下:
fn_dataBound: function (e) {
e.sender.expandRow(e.sender.tbody.find("tr.k-master-row").first());
}
模板的定義如下:
<script id="functiongridsubtemp" type="text/x-kendo-template">
<div class="functionTab">
<ul>
<li >輸入引數</li>
<li>輸出引數</li>
<li>附加屬性</li>
</ul>
<div>
<div class='inparagrid'></div>
</div>
<div>
<div class='outparagrid'></div>
</div>
<div>
<div class='expropgrid'></div>
</div>
</div>
</script>
這個模板相對複雜,在一個分頁控制元件中顯示三個網格,用於顯示函式的輸入引數、輸出引數和附加引數。需要注意的是,模板中不能用id進行標記,因為在頁面中,每一行都需要使用模板建立一組元素,在模板中定義id,不能保證id唯一。因此在函式中,需要使用class來獲取相關的元素。
Grid彈出編輯窗下拉框控制元件
如果在Grid彈出窗中有下拉框控制元件,可以使用values屬性直接繫結到陣列,在彈出編輯窗中自動生成下拉框,示例程式碼如下:
<div id="fieldgrid" class="grid"
data-role="grid"
data-sortable="true"
data-toolbar="['create']"
data-bind="source: fieldSource"
data-editable='{"mode": "popup" }'
data-columns='[
{"field":"Name","title":"欄位名稱"},
{"field":"Title","title":"欄位說明"},
{"field":"DataType","title":"欄位型別","values":dsDataType},
{"field":"ControlType","title":"控制元件型別", "values":dsControlType},
{"field":"DefaultValue","title":"預設值"},
{"field":"Editable","title":"是否可編輯"},
{"field":"Visible","title":"是否可見"},
{"field":"DisplayOrder","title":"顯示順序", editor: numberEditor},
{"field":"IsCascade","title":"是否級聯"},
{"field":"CascadeSubField","title":"級聯下級"},
{"field":"CascadeParentField","title":"級聯上級"},
{"command": [ "edit", "destroy" ], "filterable": false, "sortable": false, "width:": "240px"}
]'
data-scrollable="false">
上面的程式碼使用了mvvm的定義模式,其中DataType和ControlType欄位的values繫結到陣列,陣列定義示例如下:
var dsDataType = [
{ value: 'number', text: '數值' },
{ value: 'string', text: '字串' },
{ value: 'date', text: '日期' },
{ value: 'boolean', text: '布林' }];
var dsControlType = [
{ value: 'InputNumber', text: '數字輸入' },
{ value: 'InputText', text: '文字輸入' },
{ value: 'DatePicker', text: '日期輸入' },
{ value: 'Checkbox', text: '單選框' },
{ value: 'Selection', text: '下拉框' },
{ value: 'ComboBox', text: '級聯下拉框' }
];
陣列定義時值欄位名為value,顯示欄位名為text。在彈出編輯窗中,會自動建立為下拉框,顯示結果如下:
使用這種方法,就不需要為下拉框定製顯示控制元件了。
為Grid控制元件建立自定義彈出編輯窗
Kendo UI Grid控制元件自帶彈出窗編輯,只要在資料來源中定義schema,就可以自動生成編輯介面,程式碼如下:
<div class="form container" id="divForm">
<div id="divGrid">
<div id="mygrid" class="grid"
data-role="grid"
data-sortable="true"
data-toolbar="['create']"
data-bind="source: dataSource"
data-editable='{"mode": "popup" }'
data-columns='[
{"field":"Id","title":"ID"},
{"field":"Name","title":"姓名"},
{"field":"Age","title":"年齡"},
{"field":"JoinDate","title":"入職日期","format": "{0:yyyy-MM-dd}"},
{"field":"Sex","title":"性別","template": "#if (Sex==1){# 女 #}else{# 男 #}# "},
{"field":"Married","title":"婚姻狀況","template": "#if (Married){# 已婚 #}else{# 未婚 #}# "},
{"command": [ "edit", "destroy" ], "filterable": false, "sortable": false, "width:": "240px"}
]'
data-scrollable="false">
</div>
</div>
</div>
<script>
$(document).ready(function () {
var viewModel = kendo.observable({
dsSex: [{ value: 0, text: '男' }, { value: 1, text: '女' }],
dataSource: new kendo.data.DataSource(
{
data: [],
schema: {
model: {
id: "Id",
fields: {
Id: { editable: true, nullable: false },
Name: { validation: { required: true } },
Age: { type: "number" },
Sex: { editable: true },
JoinDate: { type: "date", editable: true },
Married: { type: "boolean", editable: true }
}
}
}
})
});
kendo.bind($("#divForm"), viewModel);
});
</script>
自動生成的編輯介面對於基本資料型別的欄位夠用了,但在實際中,會有更復雜的要求,比如,某些欄位需要使用下拉框或者更復雜的控制元件,或者我們希望欄位多列排列,這時,需要用到自定義的模板,上面的網格的自定義編輯模板如下:
<script id="popup_editor" type="text/x-kendo-template">
<div class="form container">
<div class="form-group row">
<label class="col-sm-2 control-label" for="Id">ID</label>
<div class="col-sm-4">
<input type='number' class='k-textbox' data-bind="value: Id" />
<span class="k-invalid-msg" data-for="Id"></span>
</div>
<!--</div>
<div class="form-group row">-->
<label class="col-sm-2" for="Name">姓名</label>
<div class="col-sm-4 ">
<input type='text' name="Name" class='k-input k-textbox k-valid' data-bind="value: Name" required="required" />
<span class="k-invalid-msg" data-for="Name"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="Age">年齡</label>
<div class="col-sm-4">
<input type='number' style="" data-role="numerictextbox" class='form-control' data-bind="value: Age" />
<span class="k-invalid-msg" data-for="Age"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="val_JoinDate">參加日期</label>
<div class="col-sm-4">
<input data-role="datepicker" data-culture="zh-CN" style="" class='form-control' data-bind="value: JoinDate," />
<span class="k-invalid-msg" data-for="JoinDate"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="val_Married">已婚</label>
<div class="col-sm-4">
<input type="checkbox" style="" data-bind="checked: Married," />
<span class="k-invalid-msg" data-for="Married"></span>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label" for="val_Sex">性別</label>
<div class="col-sm-4">
<select data-role="dropdownlist" class='form-control' data-text-field="text"
data-value-field="value" data-bind="source:dsSex,value: Sex">
</select>
<span class="k-invalid-msg" data-for="Sex"></span>
</div>
</div>
</div>
</script>
模板使用script標記,型別為text/x-kendo-template,說明是kendo的模板。模板語言就是html,其中的data標記與kendo MVVM一致。模板中有幾點需要注意:
- 模板中需要驗證的欄位,需要定義name屬性,如果不定義,驗證資訊無法顯示
- 需要定義 用於顯示驗證資訊
- 如果需要多列顯示,需要在頁面中定義自定義的樣式:
<style>
.k-edit-form-container {
width: 700px;
}
.k-edit-form-container div {
box-sizing: border-box;
}
.k-edit-form-container label {
box-sizing: border-box;
}
</style>
需要將相關元素的box-sizing 設定為border-box
Grid彈出編輯窗自定義編輯控制元件
上節介紹了建立自定義的彈出編輯窗體,這種方法的好處是可以完全控制編輯窗體中的各個控制元件,但也有些麻煩,如果只需要修改其中的幾個控制元件,完全重寫一個編輯窗體就顯得沒有必要了。這時,可以為單個編輯控制元件進行定製。示例程式碼如下:
<div id="commandgrid" class="grid"
data-role="grid"
data-sortable="true"
data-toolbar="['create']"
data-bind="source: commandSource"
data-editable='{"mode": "popup" }'
data-columns='[
{"field":"Name","title":"名稱"},
{"field":"Title","title":"文字"},
{"field":"FunctionName","title":"函式名稱"},
{"field":"DisplayOrder","title":"顯示順序", editor: numberEditor},
{"command": [ "edit", "destroy" ], "filterable": false, "sortable": false, "width:": "240px"}
]'
data-scrollable="false">
</div>
上面的程式碼使用了mvvm的定義方式,其中DisplayOrder欄位使用了自定義的editor,numberEditor是一個自定義的函式,在這個函式裡建立自定義的控制元件並新增到container中:
function numberEditor(container, options) {
$('<input name="' + options.field + '"/>')
.appendTo(container)
.kendoNumericTextBox({
format:"n0"
});
}
這裡定義了數字輸入的格式,不顯示小數。
根據條件改變行顯示
在網格顯示時,經常需要設定條件,根據網格中的資料,改變網格或者所在行的顯示屬性。比如如果資料超過某個限度,需要顯示報警顏色。這些需求包括當滿足一定條件時:
- 整行背景顏色改變
- 字型顏色改變
- 字型加粗
- 增加刪除線
- 當網格的第一列時核取方塊時,自動選中當前行
- 當網格的第一列時核取方塊時,不允許選擇
在Kendo Grid的dataBound事件中,可以實現上述功能。 示例程式碼如下:
dataBound: function (e) {
var rows = e.sender.tbody.children();
for (var j = 0; j < rows.length; j++) {
var row = $(rows[j]);
var dataItem = e.sender.dataItem(row);
var age = dataItem.get("AGE");
var cells = row.children();
if (age > 15) {
for (var idx = 0; idx < cells.length; idx++) {
var mytd = cells[idx];
cells[idx].bgColor = "green"; //設定行背景顏色
}
}
if (age < 15) {
for (var idx = 0; idx < cells.length; idx++) {
var mytd = cells[idx];
if (idx == 0) {
var chk = mytd.children[0];
$(chk).prop("checked", true); //設定選擇框
}
$(mytd).css("font-weight", "bold"); //設定字型
$(mytd).css("color", "red");//設定字型顏色
$(mytd).css("text-decoration", "line-through");//加刪除線
$(mytd).height(100);//設定行高
}
}
}
}