Создаем разные виды Drupal HTML таблиц (часть 1)
Опубликовано пт, 04/09/2015 - 22:23
Сегодня мы поговорим о html таблицах в друпале, а точнее о том, как их создавать. Не найдется, пожалуй, ни одного человека, кто не встречался с таблицами в друпале. Первое место, где их можно увидеть - это, конечно же, админка.
Прежде чем мы перейдем к рассмотрению различных видов таблиц, приведем сразу общий хук меню, чтобы его не повторять для каждого вида.
В файле MYMODULE.module
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * Implements hook_menu(). */ function MYMODULE_menu() { $items['test-tables'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('MYMODULE_tables_page'), // Вариант тестовый, поэтому откроем доступ всем, в реальном модуле, урл конечно нужно закрыть пермишенами. 'access callback' => TRUE, ); return $items; } |
Содержание
- Простая таблица
- Таблица с сортировкой и пейджинатором
- Draggable таблица
- Таблица с возможностью выбора строк (tableselect)
Простая таблица
Начнем с самой простой таблицы, таблицы без сортировок, иерархии и т.д.
Опишем тему, которая будет непосредственно отвечать за вывод таблицы. hook_theme()[1] также располагается в MYMODULE.module.
1 2 3 4 5 6 7 8 9 10 11 |
/** * Implements hook_theme(). */ function MYMODULE_theme() { return array( 'simple' => array( 'render element' => 'form', 'file' => 'MYMODULE.theme.inc', ), ); } |
Теперь необходимо описать функцию MYMODULE_tables_page(), которая будет отдавать рендерный массив необходимых данных. Для примера выведем все опубликованные заголовки нод и дополнительно укажем тип материала, дату создания, ссылку для редактирования. Намеренно не использовал node_load_multiple(), т.к. абсолютно незачем загружать полноценные объекты нод для получения этих данных из одной таблицы одним запросом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
/** * Get nodes titles. */ function MYMODULE_get_all_nodes() { return db_select('node', 'n') ->fields('n', array('nid', 'type', 'title', 'created')) ->condition('n.status', NODE_PUBLISHED) ->range(NULL, 10) ->execute() ->fetchAllAssoc('nid'); } /** * Example tables page. */ function MYMODULE_tables_page() { $nodes = MYMODULE_get_all_nodes(); $form['simple_table'] = array( '#type' => 'container', '#theme' => 'simple', ); foreach ($nodes as $nid => $node) { $form['simple_table'][$nid]['title'] = array( '#markup' => $node->title, ); $form['simple_table'][$nid]['type'] = array( '#markup' => $node->type, ); $form['simple_table'][$nid]['created'] = array( '#markup' => date('d-m-Y H:i', $node->created), ); $form['simple_table'][$nid]['link'] = array( '#type' => 'link', '#title' => t('Edit'), '#href' => $nid . '/edit', ); } return $form; } |
Далее очередь функции темы theme_simple(). В файле MYMODULE.theme.inc поместим следующие строки
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/** * Returns HTML for a simple table. */ function theme_simple($vars) { $form = $vars['form']; $rows = array(); foreach (element_children($form) as $id) { if (isset($form[$id])) { $rows[] = array( 'data' => array( drupal_render($form[$id]['title']), drupal_render($form[$id]['type']), drupal_render($form[$id]['created']), drupal_render($form[$id]['link']), ), 'class' => array(), ); } } // Шапка таблицы. $header = array( t('Title'), t('Type'), t('Date'), t('Action'), ); $output = theme('table', array( 'header' => $header, 'rows' => $rows, 'empty' => t('Table is empty', array()), )); $output .= drupal_render_children($form); return $output; } |
Результат приведен на изображении ниже.
Таблица с сортировкой и пейджинатором
Сортировку и постраничную навигацию можно "прицепить" практически к любой таблице. Рассмотрим изменения на примере простой таблицы, описанной выше.
Необходимо внести изменения непосредственно в сам запрос на выборку информации о нодах.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * Get nodes titles. */ function MYMODULE_get_all_nodes($header) { return db_select('node', 'n') // Добавление возможности постраничного вывода. ->extend('PagerDefault') // Добавление возможности сортировки вместе с orderByHeader(). ->extend('TableSort') ->fields('n', array('nid', 'type', 'title', 'created')) ->condition('n.status', NODE_PUBLISHED) // Ограничиваем отображение нод тремя строками. ->limit(3) // Сортировка по шапке таблицы. ->orderByHeader($header) ->execute() ->fetchAllAssoc('nid'); } |
Аргумент $header в функции MYMODULE_get_all_nodes() - это шапка будущей таблицы. Внесем следующие изменения в MYMODULE_tables_page().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
/** * Example tables page. */ function MYMODULE_tables_page() { // Шапка таблицы с указанием филдов, по которым будет производиться сортировка. $header = array( array('data' => t('Title'), 'field' => 'n.title'), array('data' => t('Type'), 'field' => 'n.type'), array('data' => t('Date'), 'field' => 'n.created'), t('Action'), ); $nodes = MYMODULE_get_all_nodes($header); $form['simple_table'] = array( '#type' => 'container', '#theme' => 'simple', // Передаем header в функцию темизации simple. '#header' => $header, ); foreach ($nodes as $nid => $node) { $form['simple_table'][$nid]['title'] = array( '#markup' => $node->title, ); $form['simple_table'][$nid]['type'] = array( '#markup' => $node->type, ); $form['simple_table'][$nid]['created'] = array( '#markup' => date('d-m-Y H:i', $node->created), ); $form['simple_table'][$nid]['link'] = array( '#type' => 'link', '#title' => t('Edit'), '#href' => $nid . '/edit', ); } // Подключаем отображение пейджинатора. $form['pager']['#markup'] = theme('pager'); return $form; } |
В MYMODULE.theme.inc передаем $header в функцию темизации table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/** * Returns HTML for a simple table. */ function theme_simple($vars) { $form = $vars['form']; $rows = array(); foreach (element_children($form) as $id) { if (isset($form[$id])) { $rows[] = array( 'data' => array( drupal_render($form[$id]['title']), drupal_render($form[$id]['type']), drupal_render($form[$id]['created']), drupal_render($form[$id]['link']), ), 'class' => array(), ); } } $output = theme('table', array( 'header' => $form['#header'], 'rows' => $rows, 'empty' => t('Table is empty', array()), )); $output .= drupal_render_children($form); return $output; } |
В итоге получаем результат
Draggable таблица
Draggable таблицы встречаются в друпале повсеместно. Это и таблица форматов текста, таблица изменения порядка фильтров, таблица управления полей для типа материала.
Как и в предыдущих примерах начинаем с объявления нашей темы.
В файле MYMODULE.module
1 2 3 4 5 6 7 8 9 10 11 |
/** * Implements hook_theme(). */ function MYMODULE_theme() { return array( 'drag_table' => array( 'render element' => 'form', 'file' => 'MYMODULE.theme.inc', ), ); } |
Функция выборки данных MYMODULE_get_all_nodes() точно такая же как и в примере с простой таблицей. Функция MYMODULE_tables_page() немного притерпит изменений с ключами элементов, названием темы и дополнительным элементом "вес", а в остальном все та же функция из 1-го примера.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
/** * Example tables page. */ function MYMODULE_tables_page() { $nodes = MYMODULE_get_all_nodes(); $form['drag_table'] = array( '#type' => 'container', '#theme' => 'drag_table', ); foreach ($nodes as $nid => $node) { $form['drag_table'][$nid]['title'] = array( '#markup' => $node->title, ); $form['drag_table'][$nid]['type'] = array( '#markup' => $node->type, ); $form['drag_table'][$nid]['created'] = array( '#markup' => date('d-m-Y H:i', $node->created), ); $form['drag_table'][$nid]['link'] = array( '#type' => 'link', '#title' => t('Edit'), '#href' => $nid . '/edit', ); // Вес. $form['drag_table'][$nid]['weight'] = array( '#type' => 'weight', '#delta' => 10, '#title' => t('Weight'), '#title_display' => 'invisible', '#default_value' => '', ); } return $form; } |
Функция темизации в MYMODULE.theme.inc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
/** * Returns HTML for a drag table. */ function theme_drag_table($vars) { $form = $vars['form']; $rows = array(); foreach (element_children($form) as $id) { // Добавляем класс для элемента "вес". $form[$id]['weight']['#attributes']['class'] = array('drag-order-weight'); if (isset($form[$id])) { $rows[] = array( 'data' => array( drupal_render($form[$id]['title']), drupal_render($form[$id]['type']), drupal_render($form[$id]['created']), drupal_render($form[$id]['link']), drupal_render($form[$id]['weight']), ), // Добавляем класс draggable для строки. 'class' => array('draggable'), ); } } // Шапка таблицы. $header = array( t('Title'), t('Type'), t('Date'), t('Action'), t('Weight'), ); $output = theme('table', array( 'header' => $header, 'rows' => $rows, 'empty' => t('Table is empty', array()), // Добавляем ID для таблицы (необходимо для добавления tableDrag поведения). 'attributes' => array('id' => 'drag-table'), )); $output .= drupal_render_children($form); // Подключение draggable поведения для таблицы. drupal_add_tabledrag('drag-table', 'order', 'sibling', 'drag-order-weight'); return $output; } |
Подробнее ознакомиться с функцией drupal_add_tabledrag() и с ее аргументами можно по ссылке[2], приведенной в дополнительных материалах в конце статьи.
Итак получаем вот такую таблицу
Таблица с возможностью выбора строк (tableselect)
Данный вид таблицы можно встретить в друпале, например, на странице контента. Объявлять свою функцию темизации нет необходимости, достаточно внести небольшие изменения в MYMODULE_tables_page().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * Example tables page. */ function MYMODULE_tables_page() { $nodes = MYMODULE_get_all_nodes(); $options = array(); foreach ($nodes as $nid => $node) { // Обращаю внимание на то, что ключи массива ячеек таблицы должны совпадать с ключами массива шапки таблицы. $options[$nid][] = $node->title; $options[$nid][] = $node->type; $options[$nid][] = date('d-m-Y H:i', $node->created); $options[$nid][] = l('Edit', $nid . '/edit'); } // Шапка таблицы. $header = array( t('Title'), t('Type'), t('Date'), t('Action'), ); $form['table_select'] = array( '#type' => 'tableselect', '#header' => $header, '#options' => $options, '#empty' => t('No content available.'), ); return $form; } |
Таблица tableselect
Материал оказался довольно объемным, поэтому остальные виды таблиц будут рассмотрены в следующей статье Создаем разные виды Drupal HTML таблиц (часть 2), а именно:
- Таблица с иерархией строк
- Draggable таблица с возможностью выбора строк
- Таблица блоков (как на странице admin/structure/blocks)
- Таблица с фильтром
Дополнительная информация по статье
- https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_theme/7 - описание hook_theme() из документации.
- https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_add_tabledrag/7 - подробное описание drupal_add_tabledrag() из документации.
- https://api.drupal.org/api/drupal/includes!theme.inc/function/theme_table/7 - описание theme_table.
- https://api.drupal.org/api/drupal/includes!form.inc/function/theme_tableselect/7 - описание theme_tableselect.
6 Comments
kalabro - вт, 08/09/2015 - 08:28
Ух ты! Ждём вторую часть)
Ух ты! Ждём вторую часть)
> Таблица блоков (как на странице admin/structure/blocks)
Совсем недавно мучилась вот с чем. Если верхний уровень делать тоже draggable (например, как будто бы можно сортировать не только блоки внутри регионов, но и сами регионы), то нельзя использовать у этих «регионов» colspan. У tabledrag.js ломается расчёт столбцов. Мелочь, а неприятно.
Алексей - вт, 16/01/2018 - 16:01
Извините, наверно очень
Извините, наверно очень глупый вопрос.
Вот я создал модуль, перенес в его файлы ***.module и ***.theme.inc, изменил названия функций, включил этот модуль, сбросил кэш.
А где я могу посмотреть результат его работы? То есть то, что у вас сразу после строки "Результат приведен на изображении ниже."
nightdevel - чт, 18/01/2018 - 23:35
Добрый вечер! В самом вверху
Добрый вечер! В самом вверху статьи я привел хук меню, в котором указан url адрес, по обращению к которому будет отрабатывать пейдж колбек drupal_get_form с переданным в него в качестве аргумента именем функции MYMODULE_tables_page. В данном случае, для просмотра результата необходимо обратиться по урлу
где SITEURL - ваш адрес сайта на локальной машине.
Алексей - пт, 16/02/2018 - 14:45
Подскажите пожалуйста.
Подскажите пожалуйста.
Dhn у вас в начале самом
написано "// Вариант тестовый, поэтому откроем доступ всем, в реальном модуле, урл конечно нужно закрыть пермишенами."
А нельзя ли пример, как это сделать?
Семён - пн, 22/03/2021 - 15:39
Нужно ли в tableselect
Нужно ли в tableselect дополнительно проверять с сабмите выбранные селекты на предмет подсовывания тех, которых нет в форме?
Например форма для удаления node и селектах id.
Гость - чт, 01/04/2021 - 11:25
можно сделать доп. проверку,
можно сделать доп. проверку, но если вы имеете ввиду модификацию формы через редактирование html кода (подсовывание новых id) - то друпал не позволит этого сделать, т.к. есть спец. токен формы, который будет проверен на предмет модификации формы.