jqGrid: использование нескольких методов для фильтрации данных
Мое требование - показать страницу с несколькими фильтрами для применения к данным сетки.
Предположим, что мы говорим о заказах, и заказ имеет следующие атрибуты
public class Order {
public int OrderID
public DateTime OrderDate
public DateTime ShipmentDate
public int OrderTotal
public int OrderStatus
}
Внутри объекта jqgrid я показываю все атрибуты, кроме OrderStatus
Требуется создать представление, которое имеет
- jqGrid в левой части
- панель справа
Внутри правой панели пользователь увидит список флажков, которые представляют все возможные значения OrderStatus, и он хочет выполнить поиск с использованием обоих методов (например, установив флажок "Отгруженные заказы", а затем отфильтровав сетку с суммой, превышающей значение)
Я уже настроил расширенную фильтрацию (multiplesearch:true
) внутри объекта jqGrid, и я могу создавать сложные фильтры, объединяющие поля и логические операторы.
Любые идеи о том, как я могу представить даже данные с правой панели, когда пользователь нажимает кнопку поиска?
Обновление 1:
Преамбула: образец Олега фантастический, но, к сожалению, не соответствует требованиям моего клиента:(
@ Олег: я не понимаю, почему вы так думаете:
Если данные находятся за пределами сетки, вы увидите детали заказа на правой панели только для выбранной строки. Так что у пользователя будет не очень хороший обзор данных.
Может быть, мое описание было не так ясно, но я не собираюсь показывать детали заказа. Чтобы лучше уточнить мои требования, я изменил ваш образец, чтобы показать вам желаемый конечный интерфейс, как на следующем рисунке:
Клиент хочет отфильтровать данные в сетке, используя два метода или оба вместе:
- С использованием
multiplesearch
средства, предоставляемые самой сеткой (спасибо за упоминание обходного пути) - Использование пользовательской панели поиска (с флажками справа)
С функциональной точки зрения требование очень легко выразить: когда пользователь нажимает на флажок или выполняет поиск с использованием нативного multiplesearch
Я должен публиковать значения на сервере, включая также состояние флажков.
Подводя итог, я должен:
- Добавить состояние флажков, когда сообщение сделано через родной
multiplesearch
- Добавить текущий
multiplesearch
состояние (если есть), когда пользователь нажимает на флажок
Есть ли способ сделать это?
2 ответа
Я понимаю это требование очень хорошо. В закрытом случае я использовал флажки внутри jqGrid. Большим преимуществом наличия информации внутри jqGrid является не только возможность легкого поиска. Если данные находятся за пределами сетки, вы увидите детали заказа на правой панели только для выбранной строки. Так что у пользователя будет не очень хороший обзор данных.
Чтобы иметь возможность разместить много флажков в таблице без постоянной горизонтальной прокрутки, я повернул заголовки столбцов, имеющих "флажок, с помощью метода, описанного в разделе" Вертикальный текст внутри заголовков таблицы ", с использованием библиотеки SVG на основе JavaScript. Это вращение выглядит не идеально в IE, но в другом браузере работает отлично.
Вы можете хранить данные из OrderStatus
поле в скрытом столбце и декодировать битовую маску в логическое значение, которое устанавливает флажки на клиенте или на стороне сервера.
Потому что использовать хотите использовать multiplesearch:true
Я должен упомянуть об ошибке в jQuery.clone, которая следует за ошибкой в мульти-поиске jqGrid во всех версиях браузеров IE. Если вы определите больше как один поисковый фильтр, будет использоваться только первый, потому что поле операций всех остальных фильтров будет читаться как undefined
, Жаль, но ошибка также не исправлена в только что опубликованном jQuery 1.4.3. Чтобы иметь возможность использовать multiplesearch:true
Вы можете использовать предложение обходного пути от Jiho Han на форуме trirand.com.
Все вместе вы можете увидеть в демонстрационном примере, который производит сетку
где вы можете искать несколько полей
Соответствующий код:
var myData = [
{ orderID: "10", orderDate: "2010-09-18", shipmentDate: "2010-09-20", orderStatus: "2" },
{ orderID: "15", orderDate: "2010-09-20", shipmentDate: "2010-09-24", orderStatus: "3" },
{ orderID: "20", orderDate: "2010-10-16", shipmentDate: "2010-10-17", orderStatus: "1" }
];
// decode 'orderStatus' column and add additional boolean data based on the bitmap mask
for (var i=0, l=myData.length; i<l; i++) {
var myRow = myData[i];
var orderStatus = parseInt(myRow.orderStatus, 10);
myRow.airPost = (orderStatus & 2) != 0? "1": "0";
myRow.heavy = (orderStatus & 1) != 0? "1": "0";
}
var grid = jQuery('#list');
grid.jqGrid({
data: myData,
datatype: 'local',
caption: 'Order Details',
height: 'auto',
gridview: true,
rownumbers: true,
viewrecords: true,
pager: '#pager',
rownumbers: true,
colNames: ['Order ID', 'Order', 'Shipment', 'Air-Post', 'Heavy', 'RowVersion'],
colModel: [
{ name: 'orderID', index: 'orderID', key:true, width: 120, sorttype: 'int' },
{ name: 'orderDate', index: 'orderDate', width: 180,
sorttype: 'date', formatter: 'date' },
{ name: 'shipmentDate', index: 'shipmentDate', width: 180,
sorttype: 'date', formatter: 'date' },
{ name: 'airPost', width: 21, index: 'airPost', formatter: 'checkbox', align: 'center',
editoptions: { value: "1:0" }, stype: 'select', searchoptions: { value: "1:Yes;0:No" } },
{ name: 'heavy', width: 21, index: 'heavy', formatter: 'checkbox', align: 'center',
editoptions: { value: "1:0" }, stype: "select", searchoptions: { value: "1:Yes;0:No" } },
{ name: 'orderStatus', index: 'orderStatus', width: 50, hidden: true }
]
}).jqGrid ('navGrid', '#pager', { edit: false, add: false, del: false, refresh: true, view: false },
{},{},{},{multipleSearch:true})
.jqGrid ('navButtonAdd', '#pager', { caption: "", buttonicon: "ui-icon-calculator", title: "choose columns",
onClickButton: function() {
grid.jqGrid('columnChooser');
}
});
где rotateCheckboxColumnHeaders
и исправление в расширенном поиске определено так
// we use workaround from http://www.trirand.com/blog/?page_id=393/bugs/in-multiple-search-second-and-subsequent-ops-are-sent-as-undefined-in-ie6/
// to fix the bug in the jQuery.clone (see http://bugs.jquery.com/ticket/6793 and
// dscussion on the http://api.jquery.com/clone/
jQuery.event.special.click = {
setup: function() {
if (jQuery(this).hasClass("ui-search")) {
jQuery(this).bind("click", jQuery.event.special.click.handler);
}
return false;
},
teardown: function() {
jQuery(this).unbind("click", jQuery.event.special.click.handler);
return false;
},
handler: function(event) {
jQuery(".ui-searchFilter td.ops select").attr("name", "op");
}
};
var rotateCheckboxColumnHeaders = function (grid, headerHeight) {
// we use grid as context (if one have more as one table on tnhe page)
var trHead = jQuery("thead:first tr", grid.hdiv);
var cm = grid.getGridParam("colModel");
jQuery("thead:first tr th").height(headerHeight);
headerHeight = jQuery("thead:first tr th").height();
for (var iCol = 0; iCol < cm.length; iCol++) {
var cmi = cm[iCol];
if (cmi.formatter === 'checkbox') {
// we must set width of column header div BEFOR adding class "rotate" to
// prevent text cutting based on the current column width
var headDiv = jQuery("th:eq(" + iCol + ") div", trHead);
headDiv.width(headerHeight).addClass("rotate");
if (!jQuery.browser.msie) {
if (jQuery.browser.mozilla) {
headDiv.css("left", (cmi.width - headerHeight) / 2 + 3).css("bottom", 7);
}
else {
headDiv.css("left", (cmi.width - headerHeight) / 2);
}
}
else {
var ieVer = jQuery.browser.version.substr(0, 3);
// Internet Explorer
if (ieVer !== "6.0" && ieVer !== "7.0") {
jQuery("span", headDiv).css("left", 0);
headDiv.css("left", cmi.width / 2 - 4).css("bottom", headerHeight / 2);
}
else {
headDiv.css("left", 3);
}
headDiv.parent().css("zoom",1);
}
}
}
};
Если вы предпочитаете держать флажки за пределами сетки, вы можете выполнить декодирование битовой маски OrderStatus
внутри обработчика события onSelectRow.
ОБНОВЛЕНО: Я действительно что-то неправильно понял ваши требования в начале. Посмотрите на модифицированный пример. Теперь похоже
и это ближе к тому, что вам нужно.
В качестве продолжения я включил здесь еще один метод, который, как я обнаружил, достиг того же результата.
Этот метод предполагает использование postData
параметр jqGrid. Внутри метода я определил различные функции, которые проверяют текущее состояние флажков и отправляют параметр на сервер, где его можно использовать для фильтрации.
Это образец
postData: {
pending: function () {
if ($("#cb_pending").is(':checked')) {
return true;
} else {
return false;
}
}
}
Преимущество этого решения по сравнению с изображенным Олегом состоит в том, что можно использовать смешанные логические операторы (И / ИЛИ) на стороне сервера, тогда как использование раздела фильтров, как в ответе Олега, невозможно.
Удачного кодирования!