1. 程式人生 > >jqGrid 單元格編輯 自定義下拉選擇框 動態資料來源 通用實現

jqGrid 單元格編輯 自定義下拉選擇框 動態資料來源 通用實現

jqGrid編輯型別可分為:單元格編輯(Cell editing)、行內編輯(Inline editing)和表單編輯(Form editing),本文討論單元格編輯模式下,下拉選擇框的通用實現。jqGrid自帶下拉選擇框編輯型別,只要設定edittype='select’並設定editoptions即可。如果顯示文字與值一致則很簡單,如果不一致,則需要通過formatter顯示文字,unformat取值,雖說程式碼量不大,但每個下拉都需要formatter和unformat,另外,如果下拉資料是動態資料來源(每行下拉資料可能不一樣),jqGrid自帶下拉就更加捉襟見肘,因此我們需要一種更通用的解決方案。

1、jqGrid自身實現

參考jqGrid user-guide,單元格編輯型別若為下拉選擇框型別,則colModel設定如下:

colModel : [
      ...
    {name:'myname', edittype:'select', editoptions:{value:{1:'One',2:'Two'}} },
      ...
]

進入單元格編輯時,jqGrid會渲染如下select:

<select>
<option value='1'>One</option>
<option value='2'>
Two</option> </select>

為了書寫方便,editoptions: { value: “FE:FedEx; IN:InTime; TN:TNT” }也可以這樣寫,注意最後沒有分號,渲染select如下:

<select>
<option value='FE'>FedEx</option>
<option value='IN'>InTime</option>
<option value='TN'>TNT</option>
</select>

2、custom edittype

jqGrid為了豐富單元格編輯型別,提供了custom edittype,自定義編輯器,user-guide如此解釋custom edittype:
This edit type allows definition of a custom editable element. When the edit type is set to custom we should provide a set of two functions, one which creates the element, and one that gets and sets the value from in form in order to be posted to the server.
The functions that should be defined are custom_element and custom_value. See the editoptions below for more details
核心就是2個東西:

  • custom_element,自定義編輯器如何顯示,UI層面
  • custom_value,自定義編輯器如何取值,資料層面

繼續user-guide提供的案例程式碼:

function myelem (value, options) {
  var el = document.createElement("input");
  el.type="text";
  el.value = value;
  return el;
}

function myvalue(elem, operation, value) {
    if(operation === 'get') {
       return $(elem).val();
    } else if(operation === 'set') {
       $(elem).val(value);
    }
}
jQuery("#grid_id").jqGrid({
...
   colModel: [
      ...
      {
        name:'price', ...,
        editable:true,
        edittype:'custom',
        editoptions: {
          custom_element: myelem,
          custom_value:myvalue
        }
      },
      ...
   ]
...
});

3、基於custom edittype的jqgrid單元格下拉編輯通用實現

1)colModel增加一個隱藏列,下拉列如下設定:

colModel: [
	...
	{label: "單位3-id", name: "unit3_id", width: 60, hidden:true},
	{label: "單位3", name: "unit3", width: 60, editable:true,
			edittype:'custom', 
			editoptions: jqgSelect({
			        		hiddenCol: "unit3_id", 
			        		dataSource: {rows: getUnit3, valueField:"value", textField:"text"}})},				
	...
]

unit3_id為隱藏列用於取值,unit3為編輯列,jqgSelect為一個通用的函式實現。

2)jqgSelect程式碼片段

	var jqgSelect = function (options) {
		/**
		 * jqgSelect是個閹割的函式,只表示可以這樣實現,給大家提供一個思路。
		 * options:{dataSource:{rows:[]|fn, valueField, textField}, hiddenCol: colName}
		 * dataSource.rows可以是一個數組,也可以是一個函式,既然是一個函式,就可以是動態資料,每行下拉資料可以不一樣.
		 * jqgrid 5.x版本,options可以直接返回rowId
		 */
		var jqgSelect_element = function (value, options) {
			//select建立, toDataSourceRows
			var ds = $.extend(true, {}, options.dataSource), colId = options.id, 
				rowId = colId.substring(0, colId.indexOf(options.name)-1),
				gridId = options.gridId || $("#" + rowId).parents("table").attr("id");
			var row = $("#" + gridId).jqGrid("getRowData", rowId);
			if(typeof ds == "object" && typeof ds.rows == "function") {
				ds.rows = ds.rows(row, gridId, rowId);
			}
			var selectOptions = "";
			for(var i = 0, l=ds.rows.length; i<l; i++) {
				selectOptions += "<option value=" + ds.rows[i][ds.valueField] + ">" + ds.rows[i][ds.textField] + "</option>";
			}
			var $select = $('<select data-gridid =' +  gridId + ' data-rowid =' + rowId + ' data-colname=' + options.name 
				+ ' data-hiddencol=' + (options.hiddenCol || "") + '>'
				+ selectOptions + '</select>');
			$select.val(row[options.hiddenCol]);
			return $select;
		}
		var jqgSelect_value = function (elem, operation, value) {
			//select value賦值
			var rowId = $(elem).data('rowid');
			var hiddenCol = $(elem).data('hiddencol');
			$("#" + $(elem).data('gridid')).jqGrid("setCell", rowId, hiddenCol, elem ? $(elem).val() : '');
			return $(elem).find('option:selected').text();
		}
		options = options || {};
		options.custom_element = jqgSelect_element;
		options.custom_value = jqgSelect_value;
		return options;
	}

3)編輯完後取值

	var rowData = $("#orders").jqGrid("getRowData","1");
	console.log("unit3_id, unit3: ", rowData.unit3_id, rowData.unit3);

4)動態資料下拉,只要設定dataSource.rows為一個函式即可。

4、案例說明

頁面截圖:
在這裡插入圖片描述
頁面程式碼:

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>jggrid多行刪除注意事項</title>
	
	<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
	<link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.5.0/css/font-awesome.min.css" />
	<link rel="stylesheet" href="https://cdn.bootcss.com/jqgrid/4.6.0/css/ui.jqgrid.css" />
	<script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
	<script src="https://cdn.bootcss.com/jqgrid/4.6.0/js/jquery.jqGrid.min.js"></script>
</head>
<body>
<div class="page-content container">
	<div class="page-head" style="padding: 15px 0"> <!-- page-head -->
		<button type="button" class="btn btn-sm" onclick="getEditCell1()">自帶select-1</button>
		<button type="button" class="btn btn-sm" onclick="getEditCell2()">自帶select-2</button>
		<button type="button" class="btn btn-sm" onclick="getEditCell3()">Custom select</button>
	</div><!-- page-head -->
	<div class="page-body"> <!-- page-body -->
		<div class="panel panel-default" id="panel-orders">
			<table id="orders"></table>
		</div>
	</div>
</div>
   
<script type="text/javascript">
	var data = [], rowIds = [];
	function getBills() {
		var rowCount = 50;
		for (var i = 0; i < rowCount; i ++) {
			data.push({
				sid: i,
				bill_id: i,
				bill_detail: i,
				goods_id: i,
				unit_id: i,
				package_id: i,
				ref_detail: i,
				goods_no: i + 1,
				goods_name: '零件名稱' + rowCount + i,
				car_type_name: '車型' + rowCount + i,
				package_name: '包裝器具' + rowCount + i,
				unit: i%2==0 ? '件' : '箱',
				unit2: i%2 + 1,
				unit3: i%2==0 ? '件' : '箱',
				snp: 0.89,
				box_count: rowCount + i,
				total_count: rowCount + i,
				goods_count: rowCount + i,
				out_count: rowCount + i,
				bill_no: 'BN0000000' + i,
			})
		}
		$("#orders").jqGrid("clearGridData").jqGrid('setGridParam',{data: data || []}).trigger('reloadGrid');
	}
	function getEditCell1() {
		var rowData = $("#orders").jqGrid("getRowData","1");
		console.log("unit: ", rowData.unit);
	}
	function getEditCell2() {
		var rowData = $("#orders").jqGrid("getRowData","1");
		console.log("unit2: ", rowData.unit2);
	}
	function getEditCell3() {
		var rowData = $("#orders").jqGrid("getRowData","1");
		console.log("unit3_id, unit3: ", rowData.unit3_id, rowData.unit3);
	}	
	function getSelectedRows() {
		console.log('getSelectedRows-rowids: ', rowIds);
	}
	function unit2Formatter(data) {
		return data == "1" ? "件" : "箱";
	}
	function unit2UnFormatter(data) {
		return data == "件" ? "1" : "2";
	}
	
	var jqgSelect = function (options) {
		/**
		 * jqgSelect是個閹割的函式,只表示可以這樣實現,給大家提供一個思路。
		 * options:{dataSource:{rows:[]|fn, valueField, textField}, hiddenCol: colName}
		 * dataSource.rows可以是一個數組,也可以是一個函式,既然是一個函式,就可以是動態資料,每行下拉資料可以不一樣.
		 * jqgrid 5.x版本,options可以直接返回rowId
		 */
		var jqgSelect_element = function (value, options) {
			//select建立, toDataSourceRows
			var ds = $.extend(true, {}, options.dataSource), colId = options.id, 
				rowId = colId.substring(0, colId.indexOf(options.name)-1),
				gridId = options.gridId || $("#" + rowId).parents("table").attr("id");
			var row = $("#" + gridId).jqGrid("getRowData", rowId);
			if(typeof ds == "object" && typeof ds.rows == "function") {
				ds.rows = ds.rows(row, gridId, rowId);
			}
			var selectOptions = "";
			for(var i = 0, l=ds.rows.length; i<l; i++) {
				selectOptions += "<option value=" + ds.rows[i][ds.valueField] + ">" + ds.rows[i][ds.textField] + "</option>";
			}
			var $select = $('<select data-gridid =' +  gridId + ' data-rowid =' + rowId + ' data-colname=' + options.name 
				+ ' data-hiddencol=' + (options.hiddenCol || "") + '>'
				+ selectOptions + '</select>');
			$select.val(row[options.hiddenCol]);
			return $select;
		}
		var jqgSelect_value = function (elem, operation, value) {
			//select value賦值
			var rowId = $(elem).data('rowid');
			var hiddenCol = $(elem).data('hiddencol');
			$("#" + $(elem).data('gridid')).jqGrid("setCell", rowId, hiddenCol, elem ? $(elem).val() : '');
			return $(elem).find('option:selected').text();
		}
		options = options || {};
		options.custom_element = jqgSelect_element;
		options.custom_value = jqgSelect_value;
		return options;
	}
	function getUnit3(row, gridId, rowId) {
		return [{value:1, text:"件"}, {value:2, text:"箱"}];
	}
	$(function() {
		$("#orders").jqGrid({
			colModel: [
				{label: "零件號", name: "goods_no", width: 60},
				{label: "零件名稱", name: "goods_name", width: 180},
				{label: "車型", name: "car_type_name"