Drupal Form API:使用AJAX再次显示相同的表单,但在提交时使用不同的值

时间:2013-02-20 13:48:25

标签: ajax drupal drupal-fapi

这是我在Stackoverflow上发表的第一篇文章,在阅读了数百个深思熟虑的问题后,也就是有用的答案。

我的观点是,今天,我从来没有找到一种(甚至是肮脏的)方式来做我打算做的事情,并且从未设法找到答案,尽管似乎很不可能没有人有同样的要求和/或问题

顺便说一句......

使用AJAX再次调用相同的表单,但其值与用户先前输入的值不同

想法

我有一个Drupal表单(使用Drupal Form API构建的普通表单),包含文本字段和一个AJAX-ified提交按钮。这个表单是通过AJAX调用显示的,本身就是AJAX-ified,所以。

当我点击“提交”时,我想做一些事情,比如查看数据库,更新某些值等,根据用户在表单中输入的内容。然后,我希望ajax-再次显示相同的表单,但其值不同于用户在表单的第一个实例中输入的值

在处理过程中做任何我想做的事情都很顺利,但无论我做什么,无论怎样,我都会一次又一次地面对同样的问题:

问题

当显示表单的新实例时,它将显示以前的值(用户输入的值)。当在表格的前一个实例中单击“提交”时,我从未能够显示表单中之前的其他值。

简单示例

我实际上要做的事情非常复杂,有几个ajax_commands和一些处理,但这是一个更简单的例子,面临完全相同的问题:

function ajax_first_callback_to_my_form($type = 'ajax') {
// here the first instance of the form is ajax-called. No problem with that.

    $mail = 'example@mail.com';
    $first_message = 'Please enter an email address...';

    $commands = array();
    $commands[] = ajax_command_replace('#my_ajax_wrapper', display_my_form($mail, $first_message));
    $page = array('#type' => 'ajax', '#commands' => $commands);
    return($page);

}

function display_my_form($mail, $message) {
// the function used to display the form.
// it can be called by the first ajax callback (the previous function in this example)
// or by the ajax callback triggered by clicking 'submit' on the form itself.

    $form = drupal_get_form('my_form', $mail, $message);

    $display = '<div id="my_ajax_wrapper">';
    $display .= render($form);
    $display .= '</div>';

    return $display;

}

function my_form($form, &$form_state, $mail, $message) {
// the form constructor

    $form = array (
        'email' => array (
            '#type' => 'textfield',
            '#default_value' => $mail,
            '#suffix' => '<div id="my_message">'.$message.'</div>',
        ),
        'submit' => array (
            '#type' => 'submit',
            '#ajax' => array (
                'callback' => 'my_ajax_callback', ),
        ),
    );

}

function my_ajax_callback($form, &$form_state) {
// triggered by clicking 'submit' in the form    

    $mail = $form_state['values']['email'];

    if ($mail == 'correct_mail@gmail.com') {
        $new_mail = 'different_mail@gmail.com';
        $new_message = 'You entered a correct email and here is your new one';
    } else {
        $new_mail = $mail;
        $new_message = 'You entered an incorrect mail, please correct it';
    }

    $commands = array();
    $commands[] = ajax_command_replace('#my_ajax_wrapper', display_my_form($new_mail, $new_message));
    $page = array('#type' => 'ajax', '#commands' => $commands);
    return($page);

}

function my_form_submit($form, &form_state) {
// my_form submit handler

    $form_state['rebuild'] = true; // appears necessary, otherwise won't work at all

}

好的,这段代码很长,但完全理解我的问题似乎很有用。

处理事情正确发生......

我想在my_form_submit或my_ajax_callback中做的所有事情都已正确完成。如果我检查display_my_form()中的变量,它们会被正确更新。

...但表单的新实例不考虑

但无论我能尝试什么,下次使用AJAX显示表单时,电子邮件字段将是'example@mail.com'作为其默认值(或用户输入的任何不同邮件),以及消息div将填写“请输入电子邮件地址......”。

我尝试了许多不同的方法,将后提交处理放在my_form_submit函数中的ajax回调中,使用$ _SESSION变量,而不是使用数据库传递它们通过不同的函数...没有这个的工作原理。

怎么做?

相当讨厌。这不是我第一次遇到这个问题。上次我找到一个解决方法,只是放弃了通过AJAX重新显示相同形式的想法,但现在我真的很希望能够做到这一点。

问题可能与$ form_state ['rebuild']有关吗?

顺便说一句,我很好奇:你以前遇到过这个问题吗?我错过了一些简单的东西吗?如果它是一个bug,这个bug可能是与Drupal相关的,还是与AJAX相关的......?

任何帮助或想法都将得到真正的赞赏。谢谢你的时间。

3 个答案:

答案 0 :(得分:1)

我想出了一个解决方案:

如果要使用AJAX再次显示相同的表单,例如使用此函数(由AJAX回调调用),无论你做什么,它都会一次又一次地显示相同的值:

// It doesn't work :

function display_my_form($mail, $message) {  

    $form = drupal_get_form('my_form', $mail, $message);

    $display = '<div id="my_ajax_wrapper">';
    $display .= render($form);
    $display .= '</div>';

    return $display;
}

如果要在刷新表单时更改字段值,则必须在再次调用表单后手动更新表单,方法是添加以下类型的行:

// It works :

function display_my_form($mail, $message) {

    $form = drupal_get_form('my_form', $mail, $message); // $variables are simply ignored if the form is already displayed. Rebuilding it won't change a thing.

    $form['email']['#default_value'] = $mail; // update a part of the form
    $form['email']['#suffix'] = $message; // update another part of the form

    $display = '<div id="my_ajax_wrapper">';
    $display .= render($form);
    $display .= '</div>';

    return $display; // sends $display to our AJAX callback, and everything's fine now

}

与简单的信念相反,一个(例如......我)可以首先了解它,该形式没有考虑使用drupal_get_form发送的变量,当已经构建并由AJAX调用时。

仅更新变量是不够的,并再次执行drupal_get_form。您必须执行drupal_get_form,然后手动更新要更新的表单部分。

希望这会对某人有所帮助。

答案 1 :(得分:0)

如果是这种情况,我对你的问题非常有信心:

$ commands [] = ajax_command_replace('#my_ajax_wrapper',display_my_form($ new_mail,$ new_message));

问题不在于它只是你传递的id。你需要一个类而不是id“#my_ajax_wrapper”,因为id可能会被改变但是在这种情况下类不会。 试试这个你应该得到你想要的结果。

答案 2 :(得分:0)

注意:要使其工作,需要在form_submit处理程序中添加它:

function my_form_submit($form, &$form_state)
{
    $form_state['rebuild'] = true;
}