Динамическое описание полей

Довольна часто мне приходится писать динамическое описание к очередному полю.

Например выбрав пользователя из списка нужно написать о нём в подписи. Одним словом нужная фича.

Сам я перепробовал кучу способов и пришёл к выводу, что удобнее всего использовать widget alter (код выходит короче и проще).

Собственно начнём с поля file которое у нас уже является ajax полем (без ajax динамики не будет).
При загрузки файла в поле меняем описание поля на "#номер имя (размер)".

HOOK, MODULE - название вашего модуля.
FORM_ID - форма где находится widget поле.
FIELD_NAME - имя поля.

/** * Implements hook_field_widget_form_alter(). */ function HOOK_field_widget_form_alter(&$element, &$form_state, $context) { $values = &$form_state['values']; $form_id = $form_state['build_info']['form_id']; $field_name = $context['field']['field_name']; $data = &$element; if (isset($element[0])) { $data = $element[0]; } switch ("{$form_id}:{$field_name}") { case 'FORM_ID:FIELD_NAME': $data['#process'][] = '_MODULE_form_field_file_process'; break; } } function _MODULE_form_field_file_process($element, &$form_state, $form) { if ($fid = $element['#value']['fid']) { $file = file_load($fid); $element['#description'] = "#{$file->fid} {$file->filename} ({$file->filesize})"; } return $element; }

Если у нас поле не ajax, но мы хотим что бы описание было динамическое - сделаем его ajax (по другому никак).
Суть такая при вводе новых данных в поле мы заменяем его на обновлённое поле с подписью.

Для замены поля нам необходимо обернуть поле в <div id="wrapper-field-user"></div>, делаем через "#prefix" и "#suffix".

$element['#prefix'] = '<div id="wrapper-field-user">'; $element['#suffix'] .= '</div>';

Зарегистрировать ajax callback срабатывающий при изменении содержимого поля.

$element['#ajax'] = array( 'event' => 'change', 'callback' => '_MODULE_replace_field_user', );

Осталось написать сам ajax callback.

$form_id - id формы.
$selector_form - css selector формы.
$selector - обёртка нашей формы.

/** * Ajax callback change field_ref_contractor */ function _MODULE_replace_field_user($form, &$form_state) { $commands = array(); $form_id = preg_replace('/_+/', '-', $form['form_id']['#value']); $selector_form = '[id^="' . $form_id . '"]'; // replace $selector = $selector_form . ' #wrapper-field-user'; $commands[] = ajax_command_replace($selector, render($form['FIELD_NAME'])); return array( '#type' => 'ajax', '#commands' => $commands, ); }

На выходе код будет таким.

/** * Implements hook_field_widget_form_alter(). */ function HOOK_field_widget_form_alter(&$element, &$form_state, $context) { $values = &$form_state['values']; $form_id = $form_state['build_info']['form_id']; $field_name = $context['field']['field_name']; $data = &$element; if (isset($element[0])) { $data = $element[0]; } switch ("{$form_id}:{$field_name}") { case 'FORM_ID:FIELD_NAME': $data['#process'][] = '_MODULE_form_field_user_process'; break; } } function _MODULE_form_field_user_process($element, &$form_state, $form) { $element['#ajax'] = array( 'event' => 'change', 'callback' => '_MODULE_replace_field_user', ); $element['#prefix'] = '<div id="wrapper-field-user">'; $element['#suffix'] .= '</div>'; $element['#description'] = rand(0, 20); return $element; } /** * Ajax callback change field_ref_contractor */ function _MODULE_replace_field_user($form, &$form_state) { $commands = array(); $form_id = preg_replace('/_+/', '-', $form['form_id']['#value']); $selector_form = '[id^="' . $form_id . '"]'; // replace $selector = $selector_form . ' #wrapper-field-user'; $commands[] = ajax_command_replace($selector, render($form['FIELD_NAME'])); return array( '#type' => 'ajax', '#commands' => $commands, ); }

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

Теги
Drupal 7.x
Form
Widget