Drupal → Создание табличной формы

01.10.2010

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

Табличная форма

Небольшая вводная информация — при создании любых табличных форм, я обычно применяю принцип прогрессивного улучшения. Т.е. первым делом создаю форму как если бы я ничего не знал о темизации, но форма при этом должна быть полностью рабочая и понятно выглядеть. Например вот так выглядит наша табличная форма без использования темизации:

Форма без темизации

Ну а вторым шагом, с помощью темизации, придаю ей необходимый вид:

Форма в виде таблицы после применения темизации

Если следовать такому принципу, то достаточно легко создавать формы любой сложности.

Итак, код с комментариями:

/**
 * Form builder.
 */
function modulename_massedit_form($form, &$form_state) {
  $form['nodes'] = array(
    '#tree' => TRUE,
    '#theme' => 'table_form', // Функция, с помощью которой мы будем придавать форме табличный вид
  );

  $nodes = db_query("SELECT nid, title, created, status FROM {node}");

  foreach ($nodes as $node) {
    $form['nodes'][$node->nid]['created'] = array(
      '#type' => 'item',
      '#title' => 'Дата создания',
      '#markup' => format_date($node->created, 'small'),
    );

    $form['nodes'][$node->nid]['title'] = array(
      '#type' => 'textfield',
      '#title' => 'Заголовок',
      '#default_value' => $node->title,
      '#required' => TRUE,
    );

    $form['nodes'][$node->nid]['status'] = array(
      '#type' => 'checkbox',
      '#title' => 'Статус',
      '#default_value' => $node->status,
    );
  }

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Сохранить',
  );

  return $form;
}

/**
 * Implements hook_theme().
 */
function modulename_theme() {
  return array(
    'table_form' => array(
      'render element' => 'form',
    ),
  );
}

/**
 * Format form as table.
 */
function theme_table_form($vars) {
  $form = $vars['form'];
  $header = isset($vars['#header']) ? $vars['#header'] : array();
  $header_created = (bool)$header;
  $rows = array();

  foreach (element_children($form) as $key) {
    foreach (element_children($form[$key]) as $name) {
      // Create header
      if (!$header_created) {
        $header[] = $form[$key][$name]['#title'];
      }

      // Hide title
      $form[$key][$name]['#title_display'] = 'invisible';

      // Cell data
      $cell = array('data' => drupal_render($form[$key][$name]));
      if (isset($form[$key][$name]['#td_attributes'])) {
        $cell += $form[$key][$name]['#td_attributes'];
      }

      $rows[$key]['data'][] = $cell;
    }

    $header_created = TRUE;

    if (isset($form[$key]['#attributes'])) {
      $rows[$key] += $form[$key]['#attributes'];
    }
  }

  return theme('table', array(
    'rows' => $rows,
    'header' => $header,
    'attributes' => isset($form['#attributes']) ? $form['#attributes'] : array(),
    'caption'    => isset($form['#caption'])    ? $form['#caption']   : NULL,
    'colgroups'  => isset($form['#colgroups'])  ? $form['#colgroups'] : NULL,
    'sticky'     => isset($form['#sticky'])     ? $form['#sticky']    : NULL,
    'empty'      => isset($form['#empty'])      ? $form['#empty']     : NULL,
  ));
}

Я уже писал про то, как создавать формы в виде таблицы, на примере формы удаления нод, но этот способ более универсальный — здесь темизируется только часть формы ($form['nodes']) и функция theme_table_form() генерирует колонки автоматически.

Рабочий пример можно посмотреть в демо-модуле.

Написанное актуально для
Drupal 7
Похожие записи

Комментарии

Гость
01.10.2010, 18:48

Уважаемый автор какой 'page callback' => должен быть в hook_menu ???

Гость
01.10.2010, 18:58

'page arguments' => array('sprice_uniona_mass_edit'), ???

Анонимус
03.10.2010, 00:33

Что делать если форма в fieldset? После drupal_render(), fieldset выводится отдельно, пустым.

$form['fieldset'] = array('#type' => 'fieldset', '#title' => 'fieldset');
$form['fieldset']['table'] = ...
$form['fieldset']['table']['header'] = ...
$form['fieldset']['table']['data'] = ...
$form['fieldset']['submit'] = ...

1) не вижу где происходит drupal_write_record().

Спасибо, нашел в примере - $node_save().
Допустим сохраняем данные кастомной таблице (прописанной в $schema) и пользователь поменял несоклько записей

$data = array ('id'=>'1', 
  'name'=> 'vasya', // (было вася)
  'gorod'=> '2', //(было 3)

$data = array ('id'=>'2', 
  'name'=> 'kolya', // (было колян)
  'gorod'=> '2', //(было 3)

Вопросец: надо каждую отдельно строку с полями сохранять drupal_write_record($table, $data, 'id') - получилось!
или можно как-то сразу все поля всех строк "хором" передать в drupal_write_record ?

semasping
03.11.2011, 23:33

Спасибо за подробные и познавательные статьи. Ваш блог очень помогает в разборках с Друпалом.

А аналог статьи по таблицам и чекбоксам для drupal 7 есть ? ... или там все так же ? Есть ли подводные камни?

Mindcircus
03.12.2012, 20:13

Хочу присоединиться к уважаемому semasping.
Огромное Вам человеческое спасибо, отличный блог.
Желаю успехов.

Станислав Романов
11.08.2013, 16:24

Кто будет делать в D7, есть небольшое отличие в API. Ниже пример для D7.

/**
 * Реализация hook_theme()
 * Регистрируем ф-ю tabular_form, которая будет собирать форму в таблицу
 */
function mymodule_theme() {
    return array(
        'tabular_form' => array('render element' => 'table'),
    );
}

/**
 * Реализация функции темизации tabular_form
 */
function theme_tabular_form($elements) {
  $rows = array();
  foreach (element_children($elements['table']['data']) as $key) {
    foreach (element_children($elements['table']['data'][$key]) as $name) {
      $rows[$key][] = drupal_render($elements['table']['data'][$key][$name]);
    }
  }

  return theme('table', array('header' => $elements['table']['header']['#value'], 'rows' => $rows));
}
Григорий
28.01.2014, 03:28

Станислав Романов, спасибо за комментарий о семерке, - очень помогло!

Можно ли в семерке в функцию темизации помимо элемента, еще и form_state передать. В частности нужно form_state['trigger_element'].

Гость
24.07.2015, 16:41

а как быть если нужена вертикальная колонка radio buttons? как их в цыкл запихнуть?

Ярослав
11.05.2016, 17:33

Пример обрадовал до слез)) пол дня лазил по англоязычным источникам, чтобы разобраться как в фиэлдсеты вывести таблицы, а тут простой рабочий пример причем в котором отлично показано как переработать отдельные части формы.

Может кому пригодится, что получилось в итоге можно глянуть тут http://pastebin.com/xxa8uRr6

Вячеслав
15.06.2022, 13:52

Будьте добры, подскажите, как заменить шаблон формирования HTML-таблиц в админке на DIV flexbox. Это ужасно реализовано в Drupal 8-9 - на мобильных устройствах неудобно наполнять сайт контентом. Всё уже перекопал - так и не смог реализовать. HOOK не работает. Хуже всего это обстоит с параграфами и добавлением картинок с Title и Alt, особенно, если у поля много значений. Пробовал просто через шаблон - всё бы хорошо, но теги TD пропадают вместе с содержимом

Добавить комментарий