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为一个函数即可。

扫描二维码关注公众号,回复: 4553745 查看本文章

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", width: 70},
				{label: "包装器具", name: "package_name", width: 70},
				{label: "单位1", name: "unit", width: 60, editable:true, edittype:'select', editoptions:{value:"件:件;箱:箱"}},
				{label: "单位2", name: "unit2", width: 60, editable:true, formatter: unit2Formatter, unformat: unit2UnFormatter,
					edittype:'select', editoptions:{value:"1:件;2:箱"}},
				{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"}})},				
				{label: "装箱率", name: "snp", width: 50, sorttype: "number"},
				{label: "箱数", name: "box_count", width: 40, sorttype: "number"},
				{label: "需求总数", name: "total_count", width: 70, sorttype: "number"},
				{label: "需求数量", name: "goods_count", width: 70,},
				{label: "出库数量", name: "out_count", width: 70, sorttype: "number"},
				{label: "订单号", name: "bill_no", width: 120},
			],
			datatype: 'local',
			rownumbers: true,
			height: 300,
			rowNum: 1000,
			cellEdit: true,
			cellsubmit: 'clientArray'
		});
		getBills();
	});
</script>
</body>
</html>

页面操作说明:

1)自带select-1

jqgrid自带下拉,显示文本与值一致,所以最简单

2)自带select-2

jqgrid自带下拉,显示文本与值不一致,所以需要:

  • unit2Formatter,显示文本
  • unit2UnFormatter,取值
3)Custom select

基于custom类型的下拉编辑框通用实现:

  • 需要colModel增加隐藏列,并在jqgSelect指定hiddenCol
  • jqgSelect,关键函数,功能上做了部分阉割,不影响工作原理说明;
  • dataSource.rows,可以是一个数组,也可以取值函数
  • getUnit3(row, gridId, rowId) ,案例的取值函数,row是该行数据,gridId表格id,rowId行号,如果是ajax请求建议使用同步请求。

猜你喜欢

转载自blog.csdn.net/chuangxin/article/details/85057023