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

~WR~

Новичок
Здравствуйте, подскажите пожалуйста как мне сделать что-то типа operAfterView, в чем задача - при просмотре записи менять ее статус.
Спасибо.
После появления диалога viewGridRow, или если запись вообще выводилась в таблице?
В первом случае есть событие beforeShowForm - можно к нему привязать обычную custom-операция.
Во втором случае, видимо, что-то обновлять в parseRow, но какой-то изврат получается. :)

SirYorik
Ок, если имена фильтра и имена колонки не совпадают, то самое простое, что можно сделать на стороне сервера:

PHP:
protected function search()
{
    parent::search();

    if(isset($this->input['countryParam']))
    {
        $this->where[] = 'country_code=' . intval($this->input['countryParam']);
    }
}
Функция search() отвечает за обычный поиск и заполняет массив условий $this->where.
Её точно так же можно заполнять и вручную, если какой-то особый случай.
 

SirYorik

Новичок
форма
PHP:
<fieldset><legend>Районы</legend>
<label>        <input type="checkbox" class="borough" checked value='ОКТ'>Октябрьский </label> &nbsp;
<label>        <input type="checkbox" class="borough" checked value='СОВ'>Советский </label> &nbsp;
<label>        <input type="checkbox" class="borough" checked value='КИР'>Кировский </label> &nbsp;
<label>        <input type="checkbox" class="borough" checked value='ЛЕН'>Ленинский </label> &nbsp;
<label>        <input type="checkbox" class="borough" checked value='ПРИ'>Пригороды </label> <br><br>
<label>        <input name="sendfilter" type="button" value="Отобрать" onclick="setFilter()"> </label>
</fieldset>
PHP:
function setFilter(){
  var boroughs = new Array();  
  $('.borough').filter(':checked').each(function(){
      boroughs.push($(this).val()); 
  });
  var boroughList = boroughs.join();
  var boroughParam = {'borough': boroughList};
  $('#jqFlats').jqGrid('setGridParam',{ 'search': true,'postData': boroughParam}).trigger('reloadGrid');
}
PHP:
protected function search()
{
    parent::search();

    if(isset($this->input['borough']))
    {
                    $parts = array();
                    $words = array_filter(explode(',', $this->input['borough']));
                    foreach($words as $w)
                    {
                        $parts[] = 'borough LIKE \'%' . $w . '%\'';
                    }
// debug output to apache error.log
$msg=  '( ' . implode(' OR ', $parts) . ' )';
file_put_contents('php://stderr', print_r($msg, TRUE));
//
                   $this->where[] =  $msg;
    }
}
Если отметить один чекбокс - то фильтр применяется верно, а в логе такой вид возврата из search()
PHP:
( borough LIKE '%ОКТ%' )
но две галки и больше возвращают пустой грид, возврат из search() при этом совершенно законный на мой взгляд, как минимум phpMyAdmin по нему нормально фильтрует
PHP:
( borough LIKE '%ОКТ%' OR borough LIKE '%СОВ%' )
может что-то вносит во {where} что-то конфиликтующее ?
как отследить финальный запрос ?


UPDATE:
строка
parent::search();
и вносит конфликт, вернее наоборот в неё вносится конфликт моим кодом,
комментирую эту строку и внешний фильтр работает по любой комбинации галок.
при этом отрубается фильтрация по поисковому тулбару. и добавляется варнинг " PHP Warning: Missing argument 1 for jqFlats::search(),"
 

~WR~

Новичок
Финальный запрос есть в JSON ответе в ключе 'debug'.
Если ключа нет, то в том месте, где настраивается jqGridLoader, добавляем строчку:
PHP:
$jq_loader->set('debug_output', true);
Ответы смотрим firebug'ом или подобным отладчиком.
На вид все правильно, если не думать про sql-инъекции в LIKE.
 

~WR~

Новичок
Включил телепатию. Думаю, у вас есть колонка с таким именем.
Поэтому он автоматически это видит и добавляет её в условие.

Запрос получается такой:
PHP:
WHERE ( borough LIKE '%ОКТ%' ) AND borough = 'ОКТ'
Но вот два значения уже не прокатывают:
PHP:
WHERE ( borough LIKE '%ОКТ%' OR borough LIKE '%СОВ%'  ) AND borough = 'ОКТ,СОВ'

Есть два варианта, и оба описаны здесь: http://jqgrid-php.net/doku.php?id=wiki:search

1. Добавить в опции колонки 'search_op' => 'ingnore'. Это выключит автоматический стандартный поиск для неё.
Будет работать только ваш custom'ный.

2. Определить новый "оператор" поиска.
Ставим опцию колонки 'search_op' => 'like_in' и добавляем в класс грида функцию с таким именем:
PHP:
protected function searchOpLikeIn($c, $val)
{
    $parts = array();
    $words = array_filter(explode(',', $val));
    foreach($words as $w)
    {
        $w = addcslashes($w, '%_');
        $parts[] = $c['db'] . ' LIKE \'%' . $w . '%\'';
    }
    return  '( ' . implode(' OR ', $parts) . ' )';
}
Я взял ваш код, только добавил в него эскейпинг для спец-символов LIKE.
Теперь можно для любой колонки поставить такой 'search_op', и поиск для неё будет работать по такому же принципу.

В последнем случае не забудьте убрать перегрузку search(), а то условие снова удвоится. :)
 

DeepNN

Новичок
Доброго времени суток !!!
Огромное спасибо автору за такую классную библиотеку...

Подскажите, возможно ли при выделении в таблице нескольких строк передавать на сервер не только id выделенных строк, но и в паре с ними соответствующие значения из какого-нибудь столбца ?
 

~WR~

Новичок
ua2fff, возможно, в сторону путей и установленных модулей в PDO.
Посмотрите firebug'ом, куда уходит запрос, и что ему возвращается. Наверняка там будет какой-нибудь warning.

PHP:
Подскажите, возможно ли при выделении в таблице нескольких строк передавать на сервер не только id выделенных строк, но и в паре с ними соответствующие значения из какого-нибудь столбца ?
Это jQuery, здесь можно всё. :)
Например:
PHP:
//Получаем id выбранных рядов
var selrow = $grid.getGridParam('selarrrow');
var other_data = [];

//Для каждого id получаем значения другой колонки и пишем в массив
for (var i in selrow) {
    other_data.push($grid.getCell(selrow[i], 'other_data'));
}

//Передаем все вместе на сервер
$grid.extRequest({
    oper: 'operation_name',
    selrow: selrow,
    other_data: other_data
});
Что угодно в этом коде можно заменить или написать по-другому.

Для получения каких-то особо хитрых значений можно напрямую дергать jQuery-селекторы.
Данные можно собирать в любые другие структуры.
Запрос на сервер можно делать через стандартный $.ajax, предварительно получив URL грида через $grid.getGridParam('url').

Полная свобода для творчества. ^__^
 

DeepNN

Новичок
~WR~
Спасибо большое за быстрый ответ.
Все что планировал получилось - передать на сервер -> принять/обработать -> запихать в БД.

Но заметил небольшой глюк, правда проявляется не всегда -
когда на отфильтрованном наборе записей осуществляется выделение всех строк установкой чекбокса "Select All", то иногда на сервер передаются не массивы id[] и other_data[], а пустые переменные id и other_data.

Глюк проявлялся на Firefox 17.0 + jQuery 1.5.2 + jqGrid 4.4.0
Другие конфигурации пока не пробовал...
 

~WR~

Новичок
Это означает, что selarrrow пустой.
Очень странно, т.к. он использует эту переменную для всех внутренних операций, касающихся выделения рядов. Всё, связанное с этим, должно было отвалиться тоже.

Возможно, где-то на этой же странице аяксом подгружается другой грид и заменяет глобальную переменную $grid. В ней всегда хранится последний созданный грид.
Попробуйте вместо $grid.getGridParam('selarrrow'); написать $(this).getGridParam('selarrrow');
 

DeepNN

Новичок
~WR~
..в браузере было открыто несколько вкладок с различными jqGrid.
Похоже selarrow и получался пустым, после того как с другим гридом поработал и вернулся к предыдущему..
Заменил $grid на $(this), больше ошибки такой не возникало....
Спасибо !!!
 

DeepNN

Новичок
~WR~
подскажите, пожалуйста, по экспорту в Excel -
1. в Google Chrome грид не разлочивается после операции экспорта;
2. можно ли как-то кастомизировать вывод в Excel - убрать "ненужные" столбцы, добавить текст до/после таблицы ?
3. в одной колонке содержатся такие данные - 16-ти значный идентификатор, только цифры, тип данных в MySQL - varchar(16), "умный" Excel считает что это число и округляет его... как от этого избавиться?

Спасибо!
Извините, если вопросы показались "детскими".

UPD:
с п.1 справился - добавил в jqgrid-ext.js к условию if(!$.browser.msie && !$.browser.opera) еще одно условие - && !$.browser.webkit
по п.2 мысли пока такие - столбцам которые не должны быть в Excel нужно при условии
PHP:
$this->out == 'export'
выставить
PHP:
"unset"  => true
только пока не пойму как;
а для вывода какого-либо текста до/после таблицы нужно перегрузить doExport
 

~WR~

Новичок
1. в Google Chrome грид не разлочивается после операции экспорта;
Да, это известная беда, связанная с различным поведением события load в разных браузерах. На новогодних праздниках посмотрю, как это обходится в jquery.form, и попробую сделать так же. Сейчас можно взять код функции extExport и убрать из него залочивание вообще. За него отвечает функция extLoading(true).

2. можно ли как-то кастомизировать вывод в Excel - убрать "ненужные" столбцы, добавить текст до/после таблицы ?
Убрать ненужные столбцы можно, перегрузив функцию output и добавив проверку.
Как-то так:
PHP:
protected function output()
{
    if($this->out == 'export')
    {
        unset($this->cols['colname']);
    }

    parent::output();
}
Добавить строки после таблицы несколько сложнее. Проще всего будет отредактировать jqGrid_Export_ExcelHtml.

3. в одной колонке содержатся такие данные - 16-ти значный идентификатор, только цифры, тип данных в MySQL - varchar(16), "умный" Excel считает что это число и округляет его... как от этого избавиться?
В parseRow можно поиграться с пробелами. Добавить их в начало или в конец, чтобы Excel интерпретировал значение как строку. Вообще да, Microsoft "молодцы" конечно со своими "умными" числами.

Вообще, тема корректного и быстрого экспорта в Excel сложна и обширна. Поэтому в jqGridPHP реализован самый простой и базовый вариант.
Если нужно что-то более сложное, то все равно мучений не избежать.
 

DeepNN

Новичок
~WR~,
PHP:
protected function output()
{
    if($this->out == 'export')
    {
        unset($this->cols['colname']);
    }

    parent::output();
}
Что-то не срабатывает....
на protected ругается, с public столбец все равно остается в xls-файле, но если убрать проверку
PHP:
if($this->out == 'export')
тогда столбца не будет в файле, но само собой и из грида тоже удаляется.
 

~WR~

Новичок
DeepNN, вторая попытка.
PHP:
protected function output()
{
    if($this->input('_out', 'json') == 'export')
    {
        unset($this->cols['colname']);
    }

    parent::output();
}
 

~WR~

Новичок
Лол. И для jQuery UI, и для jqGrid есть нормальные версии сорцов с полным форматированием. Посмотрите дистрибутивы внимательнее.
Напомнило одного знакмого, который minified-версии не только читал, но и правил. Маньяки! :)

Посмотрите, в каком контексте вызывается код. На самом деле, это хитрый тест с целью определить, насколько корректно браузер работает с конкретно указанной шириной ячеек таблицы.
Забавно, но, по-моему, Chrome имеет своё мнение насчет того, что такое <td style="width:5px;"></td>, и итоговая ширина оказывается больше за счет padding'ов. Вот это зло автор и пытается отловить.

В javascript'е вообще и в jQuery в частности постоянно делают подобные проверки. Разных косяков в браузерах нереальный зоопарк, поэтому других вариантов нет.

Ну это jQuery UI. Они любят что-нибудь поменять.
Надо посмотреть, не поменяли ли они базовую разметку. Возможно, они теперь хотят новый class там, где его раньше не было.

Вряд ли специально могли сделать так, что высота сама не подстраивается под контент. Скорее всего, просто какой-то minor change.
 

DeepNN

Новичок
~WR~
DeepNN, вторая попытка.
с этим вариантом
PHP:
protected function output()
{
    if($this->input('_out', 'json') == 'export')
    {
        unset($this->cols['colname']);
    }

    parent::output();
}
"ненужные" поля в выходном файле отсутствуют,
однако если к записям в гриде был применен фильтр с участием таких "ненужных" полей - при формировании файла данный фильтр игнорируется.

Я использовал следующее решение - добавил новую опцию колонки not_export.
В коде формирования html-таблицы строки
PHP:
if($c['hidden'] or $c['unset']) continue;
............
if($c['hidden']) continue;
заменил соответственно на
PHP:
if($c['hidden'] or $c['unset'] or $c['not_export']) continue;
............
if($c['hidden'] or $c['not_export']) continue;
При формировании грида в свойствах "ненужных" колонок указываю
PHP:
'not_export'=> true
Записи в гриде по таким полям фильтруются, файл экспорта формируется без них.
 

tyu

Новичок
Здравствуйте.
Подскажите, jqGrid может выдавать строки согласно фильтру без всяких запросов к серверу, т.е. фильтровать что есть?
 
Сверху