Как сохранить текущую строку в jqgrid
Как определить текущую строку, если сетка открывается снова или страница обновляется?
Ответ в настройках сохраняемого столбца jqGrid описывает, как сохранить ширину столбца и некоторые другие параметры.
В этом ответе на демо я щелкнул в какой-то строке и нажал F5 . Предыдущая нажатая строка не была выделена. Как сохранить / восстановить текущую строку в локальном хранилище?
Обновить
Если в приложении изменяется структура столбца jqGrid, и пользователь снова открывает приложение из браузера, restorecolumnstate создает недопустимую colmodel, в которой отсутствуют некоторые элементы. Это вызывает исключение в refreshSearchingToolbar, которое предполагает наличие всех элементов colmodel.
Как это исправить? Как вычесть модифицированный колмодол и не восстановить колмодель в этом случае? Или должны восстановить ColumnState обновить colModel, чтобы создать правильный массив?
** Обновление 2 **
Если myColumnsState.permutation содержит нули $grid.jqGrid("remapColumns", myColumnsState.permutation, true)
создал недействительный colmodel. Вот скриншоты из отладчика VS непосредственно до и после вызова remapColumns
после:
Я исправил это, изменив код на
if (isColState && myColumnsState.permutation.length > 0) {
var i, isnull = false;
for (i = 0; i < myColumnsState.permutation.length; i = i + 1) {
if (myColumnsState.permutation[i] == null) {
isnull = true;
break;
}
}
if (!isnull) {
$grid.jqGrid("remapColumns", myColumnsState.permutation, true);
}
Это лучшее решение?
2 ответа
Я соединил код из предыдущего ответа о сохранении предпочтений столбца jqGrid с кодом из другого ответа, где я предложил код, в котором реализован постоянный выбор строк. Важно отметить, что в случае multiselect:true
будет использоваться массив идентификаторов выбранных строк, который содержит все выбранные, даже если строки находятся на другой странице. Это очень практично, а реализация очень проста. Поэтому я разместил соответствующий запрос на добавление функции, но он до сих пор остается без ответа.
Теперь я могу представить два демо: первое демо, которое использует multiselect: true
и вторая демонстрация, которая использует тот же код, но с одним выбором.
Наиболее важные части кода, который я использовал, вы найдете ниже.
Очень важно упомянуть одну вещь: вы должны изменить значение myColumnStateName
на каждой странице, которую вы используете. Значение переменной содержит имя состояния столбца в localStorage
, Так что если вы не измените имя, вы будете использовать состояние разных таблиц, что может привести к очень странным эффектам. Вы можете использовать имена, созданные на основе имени текущей страницы или ее URL, в качестве значения myColumnStateName
,
var $grid = $("#list"),
getColumnIndex = function (grid, columnIndex) {
var cm = grid.jqGrid('getGridParam', 'colModel'), i, l = cm.length;
for (i = 0; i < l; i++) {
if ((cm[i].index || cm[i].name) === columnIndex) {
return i; // return the colModel index
}
}
return -1;
},
refreshSerchingToolbar = function ($grid, myDefaultSearch) {
var postData = $grid.jqGrid('getGridParam', 'postData'), filters, i, l,
rules, rule, iCol, cm = $grid.jqGrid('getGridParam', 'colModel'),
cmi, control, tagName;
for (i = 0, l = cm.length; i < l; i++) {
control = $("#gs_" + $.jgrid.jqID(cm[i].name));
if (control.length > 0) {
tagName = control[0].tagName.toUpperCase();
if (tagName === "SELECT") { // && cmi.stype === "select"
control.find("option[value='']")
.attr('selected', 'selected');
} else if (tagName === "INPUT") {
control.val('');
}
}
}
if (typeof (postData.filters) === "string" &&
typeof ($grid[0].ftoolbar) === "boolean" && $grid[0].ftoolbar) {
filters = $.parseJSON(postData.filters);
if (filters && filters.groupOp === "AND" && typeof (filters.groups) === "undefined") {
// only in case of advance searching without grouping we import filters in the
// searching toolbar
rules = filters.rules;
for (i = 0, l = rules.length; i < l; i++) {
rule = rules[i];
iCol = getColumnIndex($grid, rule.field);
if (iCol >= 0) {
cmi = cm[iCol];
control = $("#gs_" + $.jgrid.jqID(cmi.name));
if (control.length > 0 &&
(((typeof (cmi.searchoptions) === "undefined" ||
typeof (cmi.searchoptions.sopt) === "undefined")
&& rule.op === myDefaultSearch) ||
(typeof (cmi.searchoptions) === "object" &&
$.isArray(cmi.searchoptions.sopt) &&
cmi.searchoptions.sopt.length > 0 &&
cmi.searchoptions.sopt[0] === rule.op))) {
tagName = control[0].tagName.toUpperCase();
if (tagName === "SELECT") { // && cmi.stype === "select"
control.find("option[value='" + $.jgrid.jqID(rule.data) + "']")
.attr('selected', 'selected');
} else if (tagName === "INPUT") {
control.val(rule.data);
}
}
}
}
}
}
},
saveObjectInLocalStorage = function (storageItemName, object) {
if (typeof window.localStorage !== 'undefined') {
window.localStorage.setItem(storageItemName, JSON.stringify(object));
}
},
removeObjectFromLocalStorage = function (storageItemName) {
if (typeof window.localStorage !== 'undefined') {
window.localStorage.removeItem(storageItemName);
}
},
getObjectFromLocalStorage = function (storageItemName) {
if (typeof window.localStorage !== 'undefined') {
return JSON.parse(window.localStorage.getItem(storageItemName));
}
},
myColumnStateName = 'ColumnChooserAndLocalStorage2.colState',
idsOfSelectedRows = [],
saveColumnState = function (perm) {
var colModel = this.jqGrid('getGridParam', 'colModel'), i, l = colModel.length, colItem, cmName,
postData = this.jqGrid('getGridParam', 'postData'),
columnsState = {
search: this.jqGrid('getGridParam', 'search'),
page: this.jqGrid('getGridParam', 'page'),
sortname: this.jqGrid('getGridParam', 'sortname'),
sortorder: this.jqGrid('getGridParam', 'sortorder'),
permutation: perm,
selectedRows: idsOfSelectedRows,
colStates: {}
},
colStates = columnsState.colStates;
if (typeof (postData.filters) !== 'undefined') {
columnsState.filters = postData.filters;
}
for (i = 0; i < l; i++) {
colItem = colModel[i];
cmName = colItem.name;
if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') {
colStates[cmName] = {
width: colItem.width,
hidden: colItem.hidden
};
}
}
saveObjectInLocalStorage(myColumnStateName, columnsState);
},
myColumnsState,
isColState,
restoreColumnState = function (colModel) {
var colItem, i, l = colModel.length, colStates, cmName,
columnsState = getObjectFromLocalStorage(myColumnStateName);
if (columnsState) {
colStates = columnsState.colStates;
for (i = 0; i < l; i++) {
colItem = colModel[i];
cmName = colItem.name;
if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') {
colModel[i] = $.extend(true, {}, colModel[i], colStates[cmName]);
}
}
}
return columnsState;
},
updateIdsOfSelectedRows = function (id, isSelected) {
var index = idsOfSelectedRows.indexOf(id);
if (!isSelected && index >= 0) {
idsOfSelectedRows.splice(index, 1); // remove id from the list
} else if (index < 0) {
idsOfSelectedRows.push(id);
}
},
firstLoad = true;
myColumnsState = restoreColumnState(cm);
isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null;
idsOfSelectedRows = isColState && typeof (myColumnsState.selectedRows) !== "undefined" ? myColumnsState.selectedRows : [];
$grid.jqGrid({
// ... some options
page: isColState ? myColumnsState.page : 1,
search: isColState ? myColumnsState.search : false,
postData: isColState ? { filters: myColumnsState.filters } : {},
sortname: isColState ? myColumnsState.sortname : 'invdate',
sortorder: isColState ? myColumnsState.sortorder : 'desc',
onSelectRow: function (id, isSelected) {
updateIdsOfSelectedRows(id, isSelected);
saveColumnState.call($grid, $grid[0].p.remapColumns);
},
onSelectAll: function (aRowids, isSelected) {
var i, count, id;
for (i = 0, count = aRowids.length; i < count; i++) {
id = aRowids[i];
updateIdsOfSelectedRows(id, isSelected);
}
saveColumnState.call($grid, $grid[0].p.remapColumns);
},
loadComplete: function () {
var $this = $(this), i, count;
if (firstLoad) {
firstLoad = false;
if (isColState) {
$this.jqGrid("remapColumns", myColumnsState.permutation, true);
}
if (typeof (this.ftoolbar) !== "boolean" || !this.ftoolbar) {
// create toolbar if needed
$this.jqGrid('filterToolbar',
{stringResult: true, searchOnEnter: true, defaultSearch: myDefaultSearch});
}
}
refreshSerchingToolbar($this, myDefaultSearch);
for (i = 0, count = idsOfSelectedRows.length; i < count; i++) {
$this.jqGrid('setSelection', idsOfSelectedRows[i], false);
}
saveColumnState.call($this, this.p.remapColumns);
},
resizeStop: function () {
saveColumnState.call($grid, $grid[0].p.remapColumns);
}
});
$grid.jqGrid('navGrid', '#pager', {edit: false, add: false, del: false});
$grid.jqGrid('navButtonAdd', '#pager', {
caption: "",
buttonicon: "ui-icon-closethick",
title: "clear saved grid's settings",
onClickButton: function () {
removeObjectFromLocalStorage(myColumnStateName);
window.location.reload();
}
});
ОБНОВЛЕНО: я забыл упомянуть, что в случае использования multiselect: true
В варианте с jqGrid 4.3 очень важно использовать исправление, описанное здесь. В первом демо я использовал модифицированную версию jquery.jqGrid.src.js
которые включают исправление ошибки.
ОБНОВЛЕНО 2: Чтобы упростить создание уникального имени элемента локального хранилища, используемого для сохранения состояния сетки, я немного изменил демоверсии. Следующая версия демонстрации с множественным выбором и демонстрационное использование одного выбора myColumnStateName
как функция, определенная следующим образом
var myColumnStateName = function (grid) {
return window.location.pathname + '#' + grid[0].id;
}
Использование myColumnStateName
изменены соответственно. Кроме того, я расширил состояние столбца, чтобы сохранить rowNum
значение.
ОБНОВЛЕНО 3: Ответ описывает, как можно использовать новую возможность бесплатной jqGrid для сохранения состояния сетки.
Решение Олега выдает ошибку при обновлении страницы, как показано ниже.
Ошибка: Uncaught TypeError: Невозможно прочитать свойство 'el' из неопределенного
Строка: 1936 в jquery.jqGrid.src.js
var previousSelectedTh = ts.grid.headers[ts.p.lastsort].el, newSelectedTh = ts.grid.headers[idxcol].el;
Решением этой проблемы является сохранение параметра сетки lastsort и сброс его после завершения загрузки, как показано ниже.
saveColumnState = function(perm) {
...
columnsState = {
search: this.jqGrid('getGridParam', 'search'),
page: this.jqGrid('getGridParam', 'page'),
sortname: this.jqGrid('getGridParam', 'sortname'),
sortorder: this.jqGrid('getGridParam', 'sortorder'),
lastsort: this.jqGrid('getGridParam', 'lastsort'),
permutation: perm,
colStates: { }
},
...
},
loadComplete: function(data) {
...
if (isColState) {
$this.jqGrid("remapColumns", myColumnsState.permutation, true);
if(myColumnsState.lastsort > -1)
$this.jqGrid("setGridParam", { lastsort: myColumnsState.lastsort });
}
...
},