The NFine framework does not include built-in multi-selection functionality. After implementing it, I realized that such features are needed only occasionally, so future enhancements will be applied selectively to maintain consistency across the system.
Since the implementation leverages jqGrid's plugin capabilities, a few API calls were sufficient. Below is the essential code modification.
/* Adjust checkbox vertical alignment and increase width by 31px */
#gridList tr td input[type=checkbox] {
margin-top: 9px;
}
function btn_details() {
const selectedKeys = $("#gridList").jqGridRowValueMul();
if (selectedKeys.toString().includes(',')) {
$.modalAlert("Please select only one item for viewing.", "error");
return;
}
$.modalOpen({
id: "Details",
title: "View Material",
url: "/ProjectBudget/GoodsInf/Details?keyValue=" + selectedKeys,
width: "800px",
height: "650px",
btn: null
});
}
Modify framework-ui.js by adding two new methods. These can be invoked on pages requiring multi-selection.
// Retrieve values of multiple selected rows
$.fn.jqGridRowValueMul = function () {
const $grid = $(this);
return $grid.jqGrid("getGridParam", "selarrrow");
};
// Enhanced grid initialization supporting multi-selection
$.fn.dataGridMul = function (options) {
const defaults = {
datatype: "json",
autowidth: true,
rownumbers: true,
shrinkToFit: false,
gridview: true
};
const settings = $.extend(defaults, options);
const $container = $(this);
settings.onSelectRow = function () {
const $toolbar = $(".operate");
const selectedRowId = $(this).jqGrid("getGridParam", "selrow");
const isChecked = selectedRowId !== undefined && selectedRowId !== null && selectedRowId.length > 0;
if (isChecked) {
$toolbar.animate({ left: 0 }, 200);
const count = $("#gridList input[type=checkbox]:checked").length;
$(".first").find("span").text(count);
} else {
$toolbar.animate({ left: '-100.1%' }, 200);
}
$toolbar.find('.close').on('click', function () {
$toolbar.animate({ left: '-100.1%' }, 200);
});
};
settings.onSelectAll = function () {
const $toolbar = $(".operate");
const selectedRows = $(this).jqGrid("getGridParam", "selrow");
const hasSelection = selectedRows !== undefined && selectedRows !== null && selectedRows.length > 0;
if (hasSelection) {
$toolbar.animate({ left: 0 }, 200);
const count = $("#gridList input[type=checkbox]:checked").length;
$(".first").find("span").text(count);
} else {
$toolbar.animate({ left: '-100.1%' }, 200);
}
$toolbar.find('.close').on('click', function () {
$toolbar.animate({ left: '-100.1%' }, 200);
});
};
$container.jqGrid(settings);
};
Initialize the grid with multi-selection enabled:
const $gridList = $("#gridList");
$gridList.dataGridMul({
url: "/ProjectBudget/GoodsInf/GetGridJson",
height: $(window).height() - 128,
colModel: [
{ label: "Primary Key", name: "F_Id", hidden: true, key: true },
{ label: 'Material Name', name: 'GoodsName', width: 110, align: 'left' },
{ label: 'Category', name: 'GoodsStyleName', width: 110, align: 'left' },
{ label: 'Guanjia Po Number', name: 'GjpNO', width: 109, align: 'left' },
{ label: 'Specifications', name: 'GoodsSpec', width: 120, align: 'left' },
{ label: 'Unit', name: 'UnitName', width: 80, align: 'center' },
{ label: 'Brand', name: 'GoodsBand', width: 120, align: 'left' },
{ label: 'Supplier', name: 'Supplier', width: 120, align: 'left' },
{ label: 'Stock', name: 'StockReal', width: 80, align: 'center' },
{
label: "Active", name: "F_EnabledMark", width: 60, align: "center",
formatter: function (value) {
return value === 1 ? '<i class="fa fa-toggle-on"></i>' : '<i class="fa fa-toggle-off"></i>';
}
},
{ label: 'Sort Order', name: 'F_SortCode', width: 60, align: 'center' }
],
pager: "#gridPager",
multiselect: true,
sortname: 'GoodsStyleID asc,F_SortCode asc',
viewrecords: true
});
By default, edit and view actions restrict selection to a single item—any attempt to select multiple items triggers a warning. The full selection feature updates the count dynamical. Back end logic should support comma-separated IDs for batch operations. Always evaluate whether multi-selection is appropriate per page—use it only when necessary.