Разрабатываю формы с возможностью динамического добавления новых полей. Новые поля обязательны для заполнения (#required). И вот такая происходит интересная ситуация. Добавляю я новое поле, но не заполняю его. Затем пытаюсь сохранить форму. Естественно, вылазит form_set_error, что поле не заполнено. Пока все работает корректно. Затем, заполняю это поле и еще раз сохраняю форму. Форма сохраняется, но почему та после сабмита меня перебрасывает на адрес site.ru/my_module/js, то есть тот путь, который я использую как коллбэк для AHAH. Почему так происходит?
Комментарии
без кода остается только гадать
Это коллбэк для AHAH
<?php
drupal_json(array('status' => TRUE, 'data' => $output));
function rent_room_js() {
include_once 'modules/node/node.pages.inc';
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
// Get the form from the cache.
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
// We will run some of the submit handlers so we need to disable redirecting.
$form['#redirect'] = FALSE;
// We need to process the form, prepare for that by setting a few internals
// variables.
$form['#post'] = $_POST;
$form['#programmed'] = FALSE;
$form_state['post'] = $_POST;
// Build, validate and if possible, submit the form.
drupal_process_form($form_id, $form, $form_state);
// This call recreates the form relying solely on the form_state that the
// drupal_process_form set up.
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Render the new output.
$rent_rooms = $form['rooms'];
unset($rent_rooms['#prefix'], $rent_rooms['#suffix']); // Prevent duplicate wrappers.
$output = theme('status_messages') . drupal_render($rent_rooms);
}
?>
Это кнопка добавления нового поля
<?php
$form['add_room'] = array(
'#type' => 'submit',
'#value' => 'Добавить комнату',
'#submit' => array('rent_add_room_submit'),
'#ahah' => array(
'path' => 'rent/js',
'wrapper' => 'rent-rooms',
'method' => 'replace',
'effect' => 'fade',
),
);
?>
Обработчик кнопки:
<?php
function rent_add_room_submit($form, &$form_state) {
node_form_submit_build_node($form, $form_state);
unset($form_state['storage']['del_room']); //убиваем флаг удаления комнаты комнаты
$form_state['storage']['add_room'] = TRUE;
}
?>
А это валидатор всей формы
<?php
function rent_my_validator($form, &$form_state) {
unset($form_state['storage']);
}
?>
Известный баг.
Лечится путем явного задания свойства #action у формы
<?php
// Force action to FIX AHAH bug that redirects to AHAH callback uri
$type = node_get_types('type', $node);
$action = '/node/add/'. $type->type;
if ($node->nid) {
$action = '/node/'. $node->nid. '/edit';
}
$form['#action'] = $action; ?>
Что то не помогло! А где можно подробнее прочитать про этот баг?
У вас довольно нетипичный код в колбэке AHAH.
Во всех статьях по ахаху мне попадался один и тот же код, приведенный ниже:
<?php
// The form is generated in an include file which we need to include manually.
// Final rendering callback.
include_once 'modules/node/node.pages.inc';
// We're starting in step #3, preparing for #4.
//$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_state = array('storage' => NULL, 'rebuild' => TRUE); // Поскольку мне критично было не сабмитить форму каждый раз при срабатывании этой фунцкии, предыдущая строка заменена на текущую
$form_build_id = $_POST['form_build_id'];
// Step #4.
$form = form_get_cache($form_build_id, $form_state);
// Preparing for #5.
$args = $form['#parameters'];
$form_id = array_shift($args);
$form_state['post'] = $form['#post'] = $_POST;
$form['#programmed'] = $form['#redirect'] = FALSE;
// Step #5.
//$form_state['submitted'] = TRUE;
drupal_process_form($form_id, $form, $form_state);
// Unset errors
unset($_SESSION['messages']['error']);
// Step #6 and #7 and #8.
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Step #9.
$form_element_collection = $form['fieldset_model']['collection'];
$output = /* vd($form_state) . */theme('status_messages') . drupal_render($form_element_collection);
drupal_json(array('status' => TRUE, 'data' => $output));
exit;
?>
Код как раз таки типичный - практически без изменений из модуля poll
И все-таки, про этот баг где почитать!?
Удалось ли разобраться с этим багом и понять как вылечить его? У меня такая же ситуация, альтерирую форму добавляя в нее комбик с AHAH callback, после пары колбеков и ошибочных сабмитов (которые обламываются на валидации) на клиентскую сторону приходит форма с неверным action. Продибагировал чуток, оказывается AHAH постит всю форму с ahah callback path, видимо она сохраняется в кеше и на следующем полном сабмите возвращается форма из кеша, даже не перестраивается, она даже до валидации может не доползти, просто системный валидатор обязательного поля ее обламает и вернет из кеша то что было до того (форму из последнего ahah). Пока что из кода вижу что менять нужно action в алтер хуке, потому что после этого произойдет ребилд и сохранение формы в кеше, в альтер у нас форма передаётся по ссылке.
Короче, все на то смахивает что AHAH это один большой костыль над FAPI.
В принципе у меня костыль с $form['#action'] в альтер хуке лечит ситуацию, кажется побочных проблем не возникает. Для тех кто захочет воспользоваться костылем, action формы нужно поменять до того как будет вызван drupal_rebuild_form, в противном случае в кеше сохранится форма с AHAH action. Кстати, советую поменять название темы на что то типа "AHAH callback изменяет action формы", чтобы потом проще было другим найти эту ветку.
мне как-то пришлось использовать вот такой вот уродливый костыль для формы редактирования ноды:
if (!empty($node->nid)) {
$form['#action'] = url("node/{$node->nid}/edit");
}
else {
$form['#action'] = url('node/add/estate');
}
Да, типа того. У меня с самого начала было недоверие к этому АНАН-у.
Кстати, кто-нибудь в курсе, как в семерке со всем этим бардаком дело обстоит?
Не осилил ахах вообще ... Какой-то он тугой и неправильный. Черезчур хардовая завязка ...