Довольна часто мне приходится писать динамическое описание к очередному полю.
Например выбрав пользователя из списка нужно написать о нём в подписи. Одним словом нужная фича.
Сам я перепробовал кучу способов и пришёл к выводу, что удобнее всего использовать 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,
);
}
Все приготовления сделаны, сбрасываем кэш и готово.