jqGrid: редактирование табличных данных с помощью inline редакторов

13 июня, 2009
jqgrid

В одной из прошлых статей (jQuery Grid Plugin – "продвинутое" решение для создания таблиц) я рассказывал об использовании jqGrid для создания таблиц.

jqGrid представляет собой плагин к библиотеке jQuery предназначенный для работы с таблицами. С его помощью можно создавать многостраничные таблицы, выполнять сортировку и, конечно, редактировать данные.

В прошлой статье речь шла только о самых простых возможностях и, как справедливо заметили в комментариях, о самой интересной части, редактировании, не было ничего сказано. Я пообещал это исправить и сегодня постараюсь это обещание выполнить.

Прежде всего, напомню, что данные хранятся на стороне сервера (в базе данных) и плагин к ним непосредственного доступа не имеет. Он может только вызвать серверный (PHP) скрипт и передать ему новые значения.

Редактировать записи в таблице можно 2 способами.

1) В отдельном окне. При редактировании строки появляется окно со всеми полями, в которые нужно ввести новые значения. Клик по кнопке «OK» отправит данные серверу.

2) С использованием inline редакторов. В режиме редактирования текст строки заменяется полями для ввода данных. Нажатие на клавишу Enter отправляет измененные данные.

Общий принцип работы в обоих случаях один и тот же. Поэтому мы рассмотрим только один вариант (с использованием inline редакторов).

Использовать будем предыдущий пример. На данный момент он только создает таблицу с данными из базы, а мы добавим возможность их редактирования.

В тексте этой статьи приводить полный код скриптов нет смысла, остановимся только на тех моментах, которые касаются редактирования. Но вы можете скачать архив с этим примером и поэкспериментировать с демонстрационной страницей.

архив с исходным кодом

демонстрационный пример

Прежде всего, сделаем поля таблицы редактируемыми. Для этого нужно внести несколько изменений в скрипт, создающий таблицу.

  1. jQuery(document).ready(function(){
  2.     var lastSel;
  3.     jQuery("#list").jqGrid({
  4.         url:'getdata.php',
  5.         datatype: 'json',
  6.         mtype: 'POST',
  7.         colNames:['#', 'Фамилия', 'Имя', 'Отчество'],
  8.         colModel :[
  9.             {name:'id', index:'id', width:30}
  10.             ,{name:'surname', index:'surname', width:80, align:'right', editable:true, edittype:"text"}
  11.             ,{name:'fname', index:'fname', width:90, editable:true, edittype:"text"}
  12.             ,{name:'lname', index:'lname', width:80, align:'right', editable:true, edittype:"text"}
  13.             ],
  14.         pager: jQuery('#pager'),
  15.         rowNum:5,
  16.         rowList:[5,10,30],
  17.         sortname: 'id',
  18.         sortorder: "asc",
  19.         viewrecords: true,
  20.         imgpath: 'themes/basic/images',
  21.         caption: 'Данные пользователей',
  22.         ondblClickRow: function(id) {
  23.             if (id && id != lastSel) {
  24.                 jQuery("#list").restoreRow(lastSel);
  25.                 jQuery("#list").editRow(id, true);
  26.                 lastSel = id;
  27.             }
  28.         },
  29.         editurl: 'saverow.php'
  30.     });
  31. });

В строке 2 мы добавили переменную lastSel, которая служит для хранения id строки, редактируемой в данный момент.

Также немного изменились строки 10-12 (по сравнению с предыдущим примером). В них перечислены параметры ячеек таблицы и для каждой ячейки (кроме первой, в которой хранится id записи) мы добавили параметры editable:true и edittype:"text".

Первый параметр делает ячейку редактируемой, второй – указывает, что в ячейке нужно создать обычное текстовое поле. Другие значения этого параметра: textarea, checkbox и select.

После этого создаем обработчик события ondblClickRow (строки 22-28). В нем мы проверяем что пользователь кликнул по строке и эта строка в данный момент не редактируется. Восстанавливаем значения в строке, которая редактировалась перед этим (с помощью restoreRow) и переводим новую строку в режим редактирования (функция editRow).

Обратите внимание на второй параметр функции editRow. Он должен быть равен true для того, чтобы сохранение данных выполнялось при нажатии на клавишу Enter.

И последнее изменение (строка 29). В параметре editurl указываем имя серверного скрипта, который будет сохранять данные.

Теперь остается только написать серверный (PHP) скрипт (saverow.php).

  1. <?php
  2. require_once('dbdata.php');
  3.  
  4. try {
  5.     //читаем новые значения
  6.     $id = $_POST['id'];
  7.     $surname = $_POST['surname'];
  8.     $fname = $_POST['fname'];
  9.     $lname = $_POST['lname'];
  10.    
  11.     //подключаемся к базе
  12.     $dbh = new PDO('mysql:host='.$dbHost.';dbname='.$dbName, $dbUser, $dbPass);
  13.     //указываем, мы хотим использовать utf8
  14.     $dbh->exec('SET CHARACTER SET utf8');
  15.  
  16.     //определяем количество записей в таблице
  17.     $stm = $dbh->prepare('UPDATE users SET surname=?, fname=?, lname=? WHERE id=?');
  18.     $stm->execute(array($surname, $fname, $lname, $id));
  19. }
  20. catch (PDOException $e) {
  21.     echo 'Database error: '.$e->getMessage();
  22. }
  23.  
  24. // end of saverow.php

Здесь мы читаем новые значения (названия параметров в массиве $_POST совпадают с названиями столбцов таблицы) (строки 6-9).

После этого подключаемся к базе и обновляем запись (строки 11-18). Чтобы показать основную идею я максимально сократил код, убрал проверки и использовал PDO для работы с базой.

Всё, теперь можно спокойно редактировать записи в таблице.

Если есть вопросы или замечания, пишите, постараюсь ответить ;)

До встречи!

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в Ajax, JavaScript, MySQL, PHP, Web разработка View Comments

]]>
  • JtNET
    Спасибо за удаление - работает отлично, но остается проблема:
    не выходит вставка в бд пишу

    if ($_POST['oper']=='add')
    {
    $stm = $dbh->prepare('INSERT INTO price (region, district, street, level, type, all_level, all_place, life_place, kitchen, bath, angle, telefone, bathroom, type_room, balcony, price, plot, firm_telefone, about, status_house, status_city, num_room) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)');
    $stm->execute(array($region, $district, $street, $level, $type, $all_level, $all_place, $life_place, $kitchen, $bath, $angle, $telefone, $bathroom, $type_room, $balcony, $price, $plot, $firm_telefone, $about, $status_house, $status_city, $num_room));
    }

    отправляется запрос POST

    id=_empty&district=%D0%B0%D1%8B%D0%B2%D0%B0%D1%84%D1%8B%D0%B0&street=%D0%B0%D1%8B&level=%D1%8B%D0%B2%D0%B0&type=%D1%8B%D0%B2%D0%B0&all_level=%D1%8B%D0%B2%D0%B0&all_place=%D1%84%D1%8B%D0%B2%D0%B0&life_place=%D1%8B%D0%B2%D0%B0&kitchen=%D1%8B%D0%B2%D0%B0&bath=%D1%8B%D0%B2%D0%B0&angle=%D1%8B%D0%B2%D0%B0&telefone=%D1%8B%D0%B2%D0%B0&bathroom=%D1%8B%D0%B2%D0%B0&type_room=%D1%8B%D0%B2%D0%B0&balcony=%D1%8B%D0%B2%D0%B0&price=%D1%8B%D0%B2%D0%B0&firm_telefone=&oper=add


    ответ от сервера пустой. Подскажите в чем может быть дело
  • JtNET
    и еще вопрос - можно ли сделать импорт в бд из EXCEL используя JsGrid(есть ли кнопка и скрипт для этого). Вопрос возник т.к. на странице загрузки http://www.trirand.com/blog/?page_id=6 есть модуль Importing and Exporting...
  • Этот модуль поддерживает xml file, xml string, json file and json string. Т.е. данные из excel нужно будет предварительно преобразовать в один из этих форматов.

    Я бы, наверное, сделал отдельную форму для загрузки xml файла и php скрипт, который импортирует эти данные в базу. А потом смотрел бы их через jqGrid.
  • JtNET
    И еще- если я правильно понял, здесь выполняется скрипт на обновление данных в бд:

    //подключаемся к базе
    $dbh = new PDO('mysql:host='.$dbHost.';dbname='.$dbName, $dbUser, $dbPass);
    //указываем, мы хотим использовать utf8
    $dbh->exec("set character_set_client='UTF8'");
    $dbh->exec("set character_set_results='UTF8'");
    $dbh->exec("set collation_connection='UTF8_general_ci'");

    //определяем количество записей в таблице
    $stm = $dbh->prepare('UPDATE price SET region=?, district=?, street=?, level=?, type=?, all_level=?, all_place=?, life_place=?, kitchen=?, bath=?, angle=?, telefone=?, bathroom=?, type_room=?, balcony=?, price=?, plot=?, firm_telefone=?, about=?, status_house=?, status_city=?, num_room=? WHERE id=?');
    $stm->execute(array($region, $district, $street, $level, $type, $all_level, $all_place, $life_place, $kitchen, $bath, $angle, $telefone, $bathroom, $type_room, $balcony, $price, $plot, $firm_telefone, $about, $status_house, $status_city, $num_room, $id));

    а как правильно написать для добавления (на insert) и удаление (delete) данных ?
  • Удаление

    $stm = $dbh->prepare('DELETE FROM price WHERE id=?');

    $stm->execute(array($id));

    Создание

    INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2)

    $stm = $dbh->prepare('INSERT INTO price (region, district, street, level, type, all_level, all_place, life_place, kitchen, bath, angle, telefone, bathroom, type_room, balcony, price, plot, firm_telefone, about, status_house, status_city, num_room) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?));

    $stm->execute(array($region, $district, $street, $level, $type, $all_level, $all_place, $life_place, $kitchen, $bath, $angle, $telefone, $bathroom, $type_room, $balcony, $price, $plot, $firm_telefone, $about, $status_house, $status_city, $num_room));
  • JtNET
    Если выполнить стандартный код используя кнопку удаления del в навигаторе наблюдаю неполное удаление данных(остается id, т.е. насколько я понимаю скрипт обновляет строку таблицы по id, а не удаляет ее).
    Вопрос: как можно написать код, чтобы строка удалялась полностью (вместе с id)
  • А в базе данных запись остается? Или нет?
  • JtNET
    Здравствуйте. Как решить проблему с кодировкой? (при редактировании )
  • У меня не было проблем с кодировками.

    Данные отправляются ajax запросом, значит utf-8, проверяйте кодировки базы.
  • JtNET
    уже разобрался
  • JtNET
    спасибо за помощь
  • JtNET
    а как добавить кнопку button на каждую строку, чтобы при нажатии открывалось активное окно в которое передовался бы id элемента строки, например : при нажатии на кнопку открывается ссылка link.php?id=5 где 5 - это id элемента строки (грубо говоря это номер строки)
  • Есть готовый пример (Row Editing -> Custom Edit)
  • Kamil-shagaliev
    Здравствуйте! У меня такая проблема. Когда я редактирую данные через inline, то мне необходимо проверить эти данные. ДОпустим у меня столблец "количество" и допустим там значение 5. А в базе у меня значение 10. Мне необходимо, чтобы при редактировании проверялось редактируемое значение больше ли чем в базе или нет. Заранее спасибо
  • Такую проверку можно сделать ajax запросом. Т.е. нужен php скрипт, который будет проверять введенное значение, а jqgrid нужно настроить так, чтобы он отправлял эти запросы.

    Самый интересный вопрос - в какой момент отправлять ajax запрос. Тут решать вам. Перечень поддерживаемых событий здесь. Все зависит от того, в каком виде вы хотите выводить сообщение о том, что значение меньше существующего.
  • Qw1564
    выводятся пустые таблицы во всех примерах по jqGrid, с чем это может быть связано?
  • Может быть с тем, что сервер возвращает не корректные данные (или в неправильном формате). Устанавливайте firebug и проверяйте запросы и ответы от сервера.
  • Drakoniha
    Подскажите пожалуйста можно ли сделать экспорт таблицы в Excel? И если да, то какая функция?
  • Есть готовый пример. Кнопка экспорта появляется в панели навигации под таблицей (рядом с поиском).

    В этом примере добавление кнопки выполняется из php скрипта.

    Из js ее можно добавить так.
    $("#mygrid").jqgrid({
    ...
    "excelexport":true,
    });
  • Drakoniha
    Да, я видела этот пример. Но что-то у меня ни как там написано, ни как Вы написали - не работает. Может надо какой-нибудь файл подключить?
  • Но пример ведь у Вас запустился? Значит, между Вашим кодом и кодом в примере есть отличия. Попробуйте скачать полную версию jqGrid со всеми плагинами и экспериментировать с ней.
  • Drakoniha
    А у Вас нет ссылки на готовый пример где кнопка экспорта из js вызывается?
    А еще: "excelexport":true, пишется в описании таблицы, или навигатора?
  • Нет, такого примера у меня нет.

    "excelexport":true
    указывается при инициализации jqGrid, в перечне параметров таблицы.
  • Drakoniha
    Хоть что делай - не работает. А где Вы прочитали про то, что экспорт в excel именно так задается? Просто не в документации, не на сайте с демо-примерами я этого не нашла.
    Подскажите еще пожалуйста(раз с Excel у меня как-то не ладится) как можно распечатать данные из таблицы. Файл-Печать из браузера мне не подходит.
  • Смотрел здесь.
  • Андрей
    Владимир, спасибо Вам за статьи. А у меня следующая проблема - делаю редактирование в форме,
    вот код создания таблицы

    $('#tAllDataProjectManager').jqGrid({
    url: createSelectUrl(),
    editurl: '/content/dataadapter.php?myFrom=1',
    datatype: 'xml',
    mtype: 'POST',
    cellEdit: false,
    caption: 'Проекты',
    colNames: ['Наименование', 'Дата регистрации', 'Завершен', 'Дата завершения', 'Примечание'],
    colModel :
    [
    { name: 'name', index: 'name', width: 400, align: 'left', editable: true },
    { name: 'createdate', index: 'createdate', width: 150, align: 'left', datefmt: 'dd.mm.YYYY', formatter: 'date', readonly:true, editable: true },
    { name: 'isfinished', index: 'isfinished', width: 150, align: 'center', formatter: 'checkbox', editable: true, edittype: "checkbox", editoptions: {value:"1:0"} },
    { name: 'finishdate', index: 'finishdate', width: 150, align: 'left', formatter: 'date', readonly: true, editable: true },
    { name: 'comment', index: 'comment', width: 150, align: 'left', hidden: true, editable: true, editrules: {edithidden: true} }
    ],
    pager: $('#tAllDataPagerProjectManager'),
    rowNum: 25,
    rowList: [10, 25, 50, 100],
    sortname: 'createdate',
    sortorder: 'asc',
    height: 400
    }).navGrid("#tAllDataPagerProjectManager", {
    refresh: true, edit: true, add: true, del: true, search: false, view: true
    });

    немного не могу понять, куда повешать обработчик события для валидации полей и как возвратить от сервера ответ, чтобы форма редактирования сама закрывалась в случае успеха? Спасибо.
  • Закрытием формы можно управлять с помощью свойств closeAfterAdd и closeAfterEdit.

    Проверка данных определяется в colModel с помощью опции editrules. Если нужен свой обработчик можно использовать событие beforeSubmit.

    Подробности здесь.
  • Drakoniha
    Здравствуйте! Подскажите пожалуйста, как можно изменить размеры формы при добавлении новой записи. Или как добавить на нее полосу прокрутки.
  • Высоту вы указываете при создании формы

    jQuery("#editgrid").jqGrid('editGridRow',"new",{height:280,reloadAfterSubmit:false});

    Подробно параметры описаны здесь (Live Data Manipulation - Add row)
  • Frag
    Огромное спасибо автору. Стьи супер.
    С нетерпением ждем продолжения.
  • Евгений
    И снова кириллица... я задал вопрос в разделе поиск данных - когда поиск осуществляется только если в запросе цифры. Теперь догадываюсь что дело не в поиске, так как проблема и при редактировании полей. Везде где знаю прописано utf8, БД тоже в этой кодировке. При выводе данных из БД (без фильтров) выводится всё хорошо- везде где надо русские буквы. Когда добавляю в запрос условия - отрабатывает если в запросе латиница и цифры. При редактировании поля - ввожу кириллицу, записываю в БД -там кракозяблы. Смотрю firebug – в post отправляются русские буквы, ответ -пустота. Всё это на W2000 и W2003 с IIS, при этом на домашнем компе с Апачем - все в норме. Подскажите где еще посмотреть..
  • К сожалению, насчет IIS ничего конкретного сказать не могу.
    AJAX запросы всегда отправляют данные в utf8, поэтому проблема либо в БД, либо в сервере. Если БД одна и та же для apache и iis, то надо смотреть настройки сервера.
  • Евгений
    Спасибо, разобрался. В файлах php одной строчки
    $dbh->exec('SET CHARACTER SET UTF8');

    оказалось недостаточно. Просто подзабыл, что всегда вставляю магические три строчки

    $dbh->exec("set character_set_client='UTF8'");
    $dbh->exec("set character_set_results='UTF8'");
    $dbh->exec("set collation_connection='UTF8_general_ci'");

    С ними счастье:-) .Еще раз спасибо за поддержку!
  • Маленький совет. Есть два запроса, которые позволяют быстро отслеживать такие ошибки

    SHOW VARIABLES LIKE 'character%'

    SHOW VARIABLES LIKE 'collation%'
  • Галина
    Здравствуйте. Перенос по словам в заголовках у меня так и не получился. В самой таблице все отлично переносится(если содержимое строки длиннее ширины столбца), а в заголовках нет. Может кто-нибудь узнал что-то новое по этому поводу?

    Еще вот что хотела спросить: Как перезагрузить данные в таблицу после ее редактирования? Прочитала в справке, вроде есть такой метод .trigger("reloadGrid");. Только вот куда его вставить?
  • Last
    С перезагрузкой все просто вот пример, при изменении переиода или диапазона сумм перегружаем таблицу

    function gridReload(){
    lastSel=0;
    var pdate1=$('#date1').val();
    var pdate2=$('#date2').val();
    var psum1=$('#sum1').val();
    var psum2=$('#sum2').val();
    jQuery("#list").jqGrid('setGridParam',{url:'prihod.php?date1='+pdate1+'&date2='+pdate2+'&sum1='+psum1+'&sum2='+psum2+'&table=',page:1}).trigger("reloadGrid");

    }
    $("input").change(function(){gridReload();return false});
  • Денис
    Здравствуйте Владимир, я уточню свой вопрос. Как изменять динамически стандартную панель редактирования navGrid(add:false, del:false, edit:false) на navGrid(add:true, del:true, edit:true)? И еще один вопрос на счет динамического создания colModel. Как добавлять и удалять динамически столбцы?
  • Я не видел в документации такого примера. Думаю, будет проще создать таблицу заново (но не уверен :) ).
  • Last
    Если кому-то надо, ниже приведенный код, позволяет перемещаться по полям формы добавления-редактирования с помощью enter и автоматически менять , на . при введении числовых значений. Вызывается через afterShowForm: enter1



    var dop=new Object();
    function enter1(formid)
    {

    var inputs = $(formid.selector+" :input");
    //получаем все поля ввода формы
    //и если для такой формы обработчик еще не создавался, то создаем
    //нужно если несколько таблиц на одной странице
    if (!dop[formid.selector])
    {
    dop[formid.selector]=1;

    inputs.keypress(function(e)
    {
    if (e.which==13)
    {
    var i=0;
    while (inputs[i].id!=this.id) i++;
    //находим текущее поле ввода и передаем фокус следующему, либо иминитруем нажатие ОК
    if (inputs[++i].id != 'id_g')
    inputs[i].focus();
    else
    $('#sData').trigger('click');
    return false;
    }
    else
    {
    var iii=$(this).val();
    if (e.which==44 && String(parseInt(iii))!='NaN')
    {

    $(this).val(iii+'.');

    return false;
    }
    }
    }
    );
    }}
  • Спасибо!
  • Денис
    Здравствуйте Владимир, подскажите пожалуйста как динамически менять, т.е. добавлять или убирать в navgrid стандартные кнопки редактирования ??? Спасибо!!!!
  • Галина
    Здравствуйте! Подскажите пожалуйста,что нужно сделать чтобы заголовки в таблице переносились по словам? (Я про те заголовки, которые пишутся в 'colNames')
  • К сожалению, готового решения у меня нет. Могу только дать ссылку на обсуждение в форуме.
  • Tomkit
    Начинаю работать с jqgrid. Интегрировал его в Codeigniter. Все js-, css-файлы подключил (библиотека jquery, jqrid-plugin и тд). Но таблица пуста. не могу понять почему. Проверил выполнение запросов в php-файле, извлекающем данные из базы MySQL - данные извлекаются верно, post-данные (использовал его в передаче параметров php-скрипту) передаются. В общем, казалось бы, работает все, лишь одна деталь - в таблице вовсе нет строк (есть лишь заголовки столбцов, "pager" с выбором количества строк на странице и переключением страниц).
    Если у Вас есть хоть какие-то предположения, в чем может быть ошибка, прошу Вас ответить на этот коментарий)
  • Tomkit
    Нашел в чем проблема. Вот код, который формирует xml-структуру для передачи jqGrid-у:
    // Начало xml разметки
    $s = "";
    $s .= "";
    $s .= "".$page."";
    $s .= "".$total_pages."";
    $s .= "".$count."";

    // Строки данных для таблицы
    // Не забудьте обернуть
    //текстовые данные в

    while($row = mysql_fetch_assoc($result))
    {
    $s .= "";
    $s .= "";
    $s .= "". $row['region_code']."";
    $s .= "";
    $s .= "". $row['latitude']."";
    $s .= "". $row['longitude']."";
    $s .= "". $row['nbip']."";
    $s .= "";
    }
    $s .= "";

    jqGrid начал отображать данные после того, как я обрамил имена индексов массива вид $row[longitude] в $row['longitude']. То есть, всю проблему решили одинарные кавычки. Почему???! Ведь в исходном примере все работало! Но при интеграции в Codeigniter эти каычки не дали отобразить данные...

    Проблема решена. Но все же интересно, чем так мешали кавычки моему скрипту? Если у кого-то есть на это ответ - буду рад его услышать :)
  • Дело не в jqGrid, а в php. Вообще указывать ключи массива в таком виде $row[longitude] нельзя, хотя во многих случаях это будет правильно работать, потому что PHP автоматически преобразует longitude в строку.
    Но в документации сказано однозначно: "Индекс массива должен быть целым числом или строкой". Там же приведено несколько примеров, в которых описаны возможные проблемы.
  • Tomkit
    Спасибо)
  • vredin
    подскажите, пожалуйста, как понять причину ошибки когда ничего не выводится в таблице?

    1. скачал и распаковал архив
    2. импортировал таблицу в существующую таблицу
    2. отредактировал dbdata.php в соответствии с настройками денвера

    при запуске index.html выводится таблица но она пустая.. добавление echo в getdata почему-то ничего не дало
  • Посмотрите в консоли firebug'а к какому скрипту отправляется запрос. Этот скрипт должен возвращать данные таблицы в JSON или XML формате.
  • Zarema
    Здравствуйте, Владимир. Спасибо большое за статьи, очень помогло! =))
    У меня такой вопрос: можно ли в модальную форму для редактирования добавить свои элементы?
    У меня три таблицы в БД: люди, специализации и таблица связи между ними (отношение многие-ко-многим). В гриде выводится инфа по людям и также столбец, где через запятую перечислены специализации человека. Так вот в форме редактирования нужно реализовать также редактирование этих специализаций (добавление, удаление) помимо общей инфы о человеке.
    Я уже задумываюсь о том, чтобы написать свою форму, добавить свои кнопки на навигатор и свои обработчики. Но может можно как-то изменить стандартную форму?
blog comments powered by Disqus ]]>