jqGridPHP - таблицы на ajax без головной боли

~WR~

Новичок
Единственное, если я правильно понял, то afterSubmit отработает только при успешной операции
Не, не так. По-моему, там просто достаточно, чтобы с сервера вернулся код ответа 200 и хоть какое-нибудь тело ответа.
status = success это другое. Это статус xhr-объекта.

Вообще, аргументы функций лучше явно смотреть firebug'ом. У них бывает такое, что в документации написано одно, а реально уже что-то поменяли в лучшую сторону.
 

sirba

Новичок
А я всё-таки решил вписывать условие фильтра в нужный столбец сразу после загрузки грида, а потом делать $grid[0].triggerToolbar(); По крайней мере такой подход получился более универсальным. Сделал функцию аля SetFilter, в кот. передаю к какому столбцу применить фильтр и, собственно, само условие и никаких подготовительных работ делать не надо, можно применить любой фильтр по любому столбцу(ам).
Ну, а если у столбца в toolbar-е не <input type=text>, а select, то тогда чуть по-другому, надо указать selected item, а уже затем - $grid[0].triggerToolbar();.
Если заинтересует такой подход, то опишу более детально.
Здравствуйте, а можно подробнее? Спасибо
 

fandm

Новичок
Ну, у меня как-то так:
PHP:
	function ClearFilter(grid,reloadnow) {
			var mustReload = false;
			$('#gbox_'+grid).find('input:text[id^="gs_"]').each(function(){
				if($(this).val() != '') {
					mustReload = true; //Предотвращение бессмысленного ajax-запроса, если ни одно поле и так не содержало фильтра
				}
			});
			if(reloadnow){
				if(mustReload){
					$('#'+grid).jqGrid()[0].clearToolbar(true);
				}	
			}else{
				$('#'+grid).jqGrid()[0].clearToolbar(false);
			}
		}
		
		function SetFilter(grid,colname,value,clearbefore,setnow) {
			if(clearbefore){
				ClearFilter(grid,false);
			}
			$('#gbox_'+grid).find('#gs_'+colname).each(function(){
				$(this).val(value);
			});
			if(setnow){
					setTimeout(function(){
						$('#'+grid).jqGrid()[0].triggerToolbar();
					},0);
			} 
		}
Примеры вызовов:
PHP:
1. SetFilter('jqMyGrid','MYFIELD','текст',true,false); /*Прописываем фильтр в поле "MYFIELD" грида с
 id='jqMyGrid', перед этим делаем полную очистку фильтров, но фильтр сразу не применяем (полезно, 
например, когда перед применением фильтра необходимо произвести некое действие с 
функционалом грида, который так или иначе сгенерирует ajax-запрос, т.е. это предотвращение 
бесполезных промежуточных ajax-запросов, ведь последующее применение фильтра вызовом 
$('#'+grid).jqGrid()[0].triggerToolbar(); всё равно инициирует ajax-запрос). {!!!!!!!!} $('#'+grid).jqGrid()[0].triggerToolbar();
 в данном случае делаем в обработчике loadComplete у грида, иначе не сработает.{!!!!!!!!}*/

2. SetFilter('jqMyGrid','MYFIELD','текст',true,true); /*Прописываем фильтр в поле "MYFIELD" грида с 
id='jqMyGrid', перед этим делаем полную очистку фильтров, и сразу применяем фильтр*/

3. SetFilter('jqMyGrid','MYFIELD1','текст',true,false); /*Прописываем фильтр в поле "MYFIELD1" грида с 
id='jqMyGrid', перед этим делаем полную очистку фильтров, т.к. нам нужен фильтр ТОЛЬКО на 2 поля 
"MYFIELD1" и "MYFIELD2", и фильтр сразу не применяем, т.к. сначала надо добавить фильтр на поле 
"MYFIELD2"*/
SetFilter('jqMyGrid','MYFIELD2','текст',false,true); /*Прописываем фильтр в поле "MYFIELD2" грида с
 id='jqMyGrid', полную очистку фильтров не делаем, т.к. нам нужен фильтр на 2 поля "MYFIELD1" и 
"MYFIELD2", и сразу применяем фильтр*/

4. ClearFilter('jqMyGrid',true); /*Очищаем все фильтры по всем полям и сразу же делаем перезагрузку 
грида*/

5. ClearFilter('jqMyGrid',true); /*Очищаем все фильтры по всем полям, но сразу перезагрузку грида не 
делаем (иногда требуется и такое)*/
Соответственно в случае, если в toolBar-е определённого столбца не просто текстовое поле, а select, то лучше воспользоваться советом ~WR~, наверное (в плане проверки был ли фильтр до этого в ClearFilter, если оно вообще надо, конечно). Или же для таких столбцов сделать спец. обработку.
 

fandm

Новичок
Не, не так. По-моему, там просто достаточно, чтобы с сервера вернулся код ответа 200 и хоть какое-нибудь тело ответа.
status = success это другое. Это статус xhr-объекта.
Таки Вы были правы. Поэтому решил задачу так:
PHP:
				afterSubmit : function( response,postdata ){ //После Update или Insert
						var json=response.responseText;
						var result=eval("("+json+")");
						if(result.success){
							/*...
							действия в случае положительного результата
							...*/
						} else {
							/*...
							действия в случае отрицательного результата
							...*/
						}
						return [result.success,result.msg,null]; 
					}
 

sirba

Новичок
Опять про фильтры, возможно вопрос покажется глупым ))), Как я могу в фильтр по примере ~WR~ указать значения get или post
 

fandm

Новичок
Не понял вопрос.
Что Вы понимаете под
значения get или post
?

А пример ~WR~ был приведён как наиболее правильный вариант обнуления (очистки) полей фильтра в FilterToolbar (в шапке грида которые).
 

sirba

Новичок
Я ссылку не туда написал
С примера
PHP:
public function output()
{
    if($this->input('_search') !== 'true')
    {
        $this->input['status'] = 1;
    }

    parent::output();
}
там где 1 прописать аля $_GET['status']
 

fandm

Новичок
там где 1 прописать аля $_GET['status']
Стоп... Так $this->input - это и есть массив $_REQUEST, насколько я понимаю. Так что всё равно не понимаю Ваш вопрос. :)

Смотрите, здесь ~WR~, насколько я понял, предложил Вам следующее.
Предположим, у Вас есть столбец 'status', на который Вы хотите наложить фильтр сразу же после загрузки грида. Если Вам не подходит описанный мною вариант, то Вы можете в своём наследнике класса грида предусмотреть реакцию на $_GET['status'], подставляя его в $this->query. А чтобы подать на вход этот самый $_GET['status'], Вам и необходимо перегрузить функцию $this->output() и сымитировать отправку этого самого $_GET['status']. Для этого и используется массив $this->input. Т.е. Вы пишете $this->input['status'] = 1; "1", в данном случае, это 1-й элемент вашего select+а.
 

sirba

Новичок
Вопрос явно ламерский......например при переходе по ссылке http://jqgrid-php.net/examples/?render=jqSimple - строится грид со всем записями, а при переходе по ссылке http://jqgrid-php.net/examples/?render=jqSimple&status=2 - строится грид с уже установленным фильтром status=2 и записи уже тоже отобранны, но в селекте есть все варианты статусов.....Как то так
 

fandm

Новичок
а при переходе по ссылке http://jqgrid-php.net/examples/?render=jqSimple&status=2 - строится грид с уже установленным фильтром status=2 и записи уже тоже отобранны, но в селекте есть все варианты статусов
Всё верно. Читайте выше, я обновил свой ответ.
Но не забудьте про
В defaultValue указываем ключ того значения, которое должно быть выбрано по умолчанию.
, иначе фильтр применится, а в FilterToolbar не будет содержаться то самое значение фильтра. В Вашем случае не будет выбран тот элемент select-а, по которому Вы применили фильтр.
 

sirba

Новичок
Сделал как в примере
PHP:
'searchoptions' => array('value' => $my_values, 'defaultValue' => $_GET['status']);
Переопределил функцию output
PHP:
public function output()
{
    if($this->input('_search') !== 'true')
    {
        $this->input['status'] =  $_GET['status'];
    }

    parent::output();
}
В результате фильтр установлен правильно, а к записям фильтр не применился - отображаются все
 

fandm

Новичок
В результате фильтр установлен правильно, а к записям фильтр не применился - отображаются все
Попробуйте к гриду добавить обработчик:
PHP:
loadComplete : function( data ){
						setTimeout(function(){
							$(this).triggerToolbar();
						},0);
}
UPDATED.
Погодите-ка, а Вы этот самый $_GET['status'] или $_REQUEST['status'] в $this->query учли? :)

Тут уже Вам надо выбирать. Или применить фильтр посылом с клиента triggerToolbar() или ещё на серверной стороне учесть условие "AND status = ".$_REQUEST['status']." " в $this->query
 

sirba

Новичок
Если я учту его в $this->query, при оновлении селекта фильтра у меня ничего не будет происходить - только с определенным статусом и все
 

fandm

Новичок
Если я учту его в $this->query, при оновлении селекта фильтра у меня ничего не будет происходить - только с определенным статусом и все
Ничего не понимаю. А что Вам мешает сделать анализ типа такого:
PHP:
		if (isset($_GET['status'])) {
			if ($_GET['status'] == '') { //Или какое у Вас там значение для элемента "Все"? Обычно пустое.
				$this->query = "select {fields} from YourTable
								where {where}";
			} else {
				$this->query = "select {fields} from YourTable
								where status=".$_GET['status']."
								AND {where}";
			}				
		} else {
				$this->query = "select {fields} from YourTable
								where {where}";
		}
?

Даже упрощая:
PHP:
			if (!isset($_GET['status']) || $_GET['status'] == '') {
				$this->query = "select {fields} from YourTable
								where {where}";
			} else {
				$this->query = "select {fields} from YourTable
								where status=".$_GET['status']."
								AND {where}";
			}
Я Вам потому и дал вариант, который не требует переопределения $this->output() и $this->query.
 

~WR~

Новичок
В общем, чтобы лишние слова не писать, доработал один из примеров:
http://jqgrid-php.net/examples/?render=jqOutSearch&delivery_type=2&price=>1000

Обратите внимание на то, как передаются дополнительные аргументы в адресной строке, и как соответствующие им фильтры выставляются на старте.

За это отвечают две последние функции. Посмотрите, там буквально пять строк.

По input'у. Его суть в следующем.
В jqGridPHP есть одна точка входа для входящих данных: функция getInputData. Она и формирует содержимое массива $this->input. В ней сейчас просто копируется содержимое $_REQUEST и применяется iconv, если кодировка грида отличается от utf-8. Больше в коде нет ни одного места, где использовались бы суперглобалы.

Перегрузив эту функцию, вы можете "обмануть" грид.
Например, часть данных можно брать не из $_REQUEST, а из какого-нибудь файла настроек. Или можно определить значения по умолчанию для входящих переменных, которые отсутствуют. При этом вообще не нужно вмешиваться в код базового класса. Всё стандартное работает только с $this->input.
 

~WR~

Новичок
PHP:
where status=".$_GET['status']."
Покусаю за такие советы. Где экранирование входящих данных?
Кто-то же ведь возьмет и скопирует. -__-
 

sirba

Новичок
Спасибо большое - все работает именно так как я хотел )))))
 

fandm

Новичок
Покусаю за такие советы. Где экранирование входящих данных?
Я просто побоялся усложнять пример, учитывая, что даже такой простой пример вызвал затруднения. :) Хотел обратить внимание на принцип, в первую очередь.

Кто-то же ведь возьмет и скопирует. -__-
Ну, эт да. Но... С таким же успехом, человек, который бездумно это скопирует, так же поступит и с остальным кодом, со всеми вытекающими. :)

Так что извиняюсь. :)

Может таки ещё добавить пример и с применением фильтра на клиенте? ;)
Может кому-то пригодится и такой вариант. Практика показывает, что готовые работающие примеры - доходчивее. :)
 

fandm

Новичок
Кстати, а что, если надо тут же снять все фильтры? Ну, вот вывели мы пользователю записи с Delivery Type = 2 и price >1000, а он посмотрел и захотел посмотреть все записи. Как это сделать? Последовательно вручную убрать все фильтры из FilterToolbar для всех столбцов (убрать текст >1000 и выставить Delivery в All), а потом нажать Enter? :) Или же придётся добавлять свою кнопку в navBar типа "Снять все фильтры".

А в случае наложения фильтра на клиенте, достаточно просто нажать Refresh и выполнится исходный SQL, который выводит все записи. ;)
 
Сверху