Сохранение настроек столбца jqGrid
У меня есть несколько jqGrids в моем приложении ASP.NET MVC 3, которые имеют несколько столбцов. Я добавил следующее в определения столбцов, чтобы по умолчанию некоторые столбцы были скрыты:
colModel: [
{ name: 'IceCreamID', hidden: true},
{ name: 'RecipeID', hidden: true }
и это прекрасно работает. Эти столбцы не видны на моей сетке.
Затем я добавил это для реализации выбора столбца:
var grid = $('#icecreamGrid');
grid.jqGrid('navButtonAdd', '#icecreamPager',
{ caption: "Columns", buttonicon: "ui-icon-calculator",
title: "Choose Columns",
onClickButton: function() {
grid.jqGrid('columnChooser');
}
});
Отлично, теперь поднимается окно выбора столбцов. Затем я добавил следующее к столбцам, которые я никогда не хотел показывать в окне выбора столбцов:
colModel: [
{ name: 'IceCreamID', hidden: true, hidedlg: true},
Так что теперь я могу просто скрыть / показать столбцы. Теперь, как бы вы сохранили эту информацию? DB? Как печенье? Другой путь? Есть ли предпочтительный способ хранения информации такого рода, которая на самом деле является предпочтением пользователя, а не чем-то связанным с самими данными?
Больше информации
Основываясь на комментариях Олега ниже, я хочу предоставить немного больше информации.
Дело в том, что у меня есть сетки с 10-15 столбцами, которые могут отображаться в зависимости от предпочтений пользователя. Для простого примера, одна из моих сеток имеет следующие 9 столбцов:
IceCream|ShortName|HasNuts|SugarAdded|LimitedRun|PromoItem|Facility|FirstRun|LastRun
Пользователи могут скрыть / показать любой из этих 9 столбцов в зависимости от своих личных предпочтений.
То, что я хочу сделать, - это предоставить способ сохранить, какие столбцы хочет видеть конкретный пользователь, чтобы ему / ей не пришлось повторно выбирать эти столбцы для просмотра каждый раз, когда отображается страница с этой сеткой.
1 ответ
Я нашел ваш вопрос очень интересным. Вопрос о сохранении пользовательского состояния сетки интересен во многих случаях. Есть несколько интересных ответов на такие проблемы, которые использует cookie (см. Здесь, например).
По моему мнению сохранение состояния сетки в базе данных на сервере или в localStorage
это лучший способ, как использование куки. Лучший способ зависит от требований проекта, в которых вы его используете. Например, использование хранилища базы данных на сервере позволяет реализовать роуминговое состояние сетки. Если вы используете localStorage
вместо файлов cookie пользовательские настройки будут потеряны, если пользователь перейдет на другой компьютер или просто если пользователь будет использовать другой веб-браузер на том же компьютере.
Другая проблема с состоянием сетки - это обслуживание. Информация о столбцах таблицы обычно хранится в файлах JavaScript или HTML, а не в базе данных. В случае, если оба источника могут быть не синхронными при изменениях сетки. Вы можете легко представить различные сценарии проблемы обновления. Тем не менее преимущества пользовательских предпочтений настолько велики в некоторых сценариях, что проблемы с небольшими недостатками не так важны и могут быть решены относительно легко.
Поэтому я потрачу некоторое время на реализацию двух демонстраций, которые покажут, как это можно реализовать. я использовал localStorage
в моих демонстрациях по многим причинам. Я упоминаю только два оттуда:
- Файлы cookie - это способ, с помощью которого на сервер или с сервера отправляется постоянно различная информация, которая на самом деле не требуется. Это увеличивает размер HTTP-заголовка и снижает производительность веб-сайта (см. Здесь, например).
- Куки имеют очень жесткие ограничения. Соответствует разделу 6.3 rfc2109 или 6.1 rfc6265: не менее 4096 байт на файл cookie, минимум 50 файлов cookie на домен (20 в rfc2109), всего не менее 3000 файлов cookie (300 в rfc2109). Таким образом, файлы cookie нельзя использовать для сохранения слишком большого количества информации. Например, если вы хотите сохранить состояние каждой сетки каждой вашей веб-страницы, вы можете быстро достичь ограничений.
На другой стороне localStorage
поддерживаются всеми современными браузерами и будут поддерживаться в Internet Explorer, начиная с IE8 (см. здесь). localStorage
будет автоматически сохранено для каждого источника (например, a1.example.com, a2.example.com, a3.example.com и т. д.) и имеет произвольный лимит 5 МБ на источник (см. здесь). Так что, если вы будете использовать пространство осторожно, вы будете далеко от любых ограничений.
Так что я использовал в своих демонстрациях localStorage
, Я должен также упомянуть, что есть некоторые плагины, такие как jStorage, которые используют localStorage
если он поддерживается браузером и использует другое хранилище, но тот же интерфейс для вас в случае старых браузеров, таких как IE6/IE7. В случае, если у вас есть только меньший размер хранилища: 128 КБ вместо 5 МБ, но лучше, чем 4 КБ, который используется для файлов cookie (см. Здесь).
Теперь о внедрении. Я создаю две демонстрации: это и его расширенная версия: это.
В первой демонстрации следующие состояния сетки будут сохранены и автоматически восстановлены при перезагрузке страницы (F5 в большинстве веб-браузеров):
- какие столбцы скрыты
- порядок столбцов
- ширина каждого столбца
- имя столбца, по которому будет сортироваться сетка, и направление сортировки
- номер текущей страницы
- текущий фильтр сетки и флаг применения фильтра. я использовал
multipleSearch: true
установка в сетке.
Таким же образом можно расширить (или уменьшить) список опций, которые являются частью сохраненного состояния сетки.
Наиболее важные части кода из демоверсии вы найдете ниже:
var $grid = $("#list"),
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 $.parseJSON(window.localStorage.getItem(storageItemName));
}
},
myColumnStateName = 'ColumnChooserAndLocalStorage.colState',
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,
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;
},
firstLoad = true;
myColumnsState = restoreColumnState(cm);
isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null;
$grid.jqGrid({
// ... other 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',
loadComplete: function () {
if (firstLoad) {
firstLoad = false;
if (isColState) {
$(this).jqGrid("remapColumns", myColumnsState.permutation, true);
}
}
saveColumnState.call($(this), this.p.remapColumns);
}
});
$grid.jqGrid('navButtonAdd', '#pager', {
caption: "",
buttonicon: "ui-icon-calculator",
title: "choose columns",
onClickButton: function () {
$(this).jqGrid('columnChooser', {
done: function (perm) {
if (perm) {
this.jqGrid("remapColumns", perm, true);
saveColumnState.call(this, perm);
}
}
});
}
});
$grid.jqGrid('navButtonAdd', '#pager', {
caption: "",
buttonicon: "ui-icon-closethick",
title: "clear saved grid's settings",
onClickButton: function () {
removeObjectFromLocalStorage(myColumnStateName);
}
});
Будьте осторожны, чтобы определить myColumnStateName
(значение `'ColumnChooserAndLocalStorage.colState'``) в демоверсии) к различным значениям на разных страницах.
Вторая демонстрация является продолжением первой, используя технику из моего старого ответа на другой ваш вопрос. Демонстрация использует панель инструментов поиска и дополнительно синхронизирует информацию между формой расширенного поиска и панелью инструментов поиска.
ОБНОВЛЕНО: Следующий ответ содержит расширенную версию кода, включенного выше. Он показывает, как сохранить выбранные строки (или строки) дополнительно. Другой ответ показывает, как сохранить список развернутых узлов древовидной сетки и развернуть узлы при повторном кодировании страницы.