在 Drupal 7 中,为什么使用来自不同模块的表单会导致其 AJAX 提交行为不正确?

发布于 2024-12-27 11:14:47 字数 4035 浏览 4 评论 0原文

我的 Drupal 7 应用程序中有一个名为“反馈”的模块。它包括一个用于提交简单反馈的表格。该表单是通过 AJAX 提交的,我已经测试并验证了提交处理。在我的反馈模块中,我最初通过 hook_menu 硬编码了此表单的位置。然后我决定希望它更加灵活 - 在我称为登陆页面的不同内容类型上,用户可以选中一个框以包含反馈表单。当他们这样做时,我只需执行 ,将其拉入。反馈表单定义位于名为 feedback.admin.inc 的文件中,因此我还必须添加 让它出现。

表单出现,但其 AJAX 处理程序不再工作。通过 Chrome 检查传出网络流量,AJAX 请求似乎被发送到通用 Drupal AJAX 处理程序。因此,当我的函数 feedback_form 在反馈模块中被调用时,表单可以正常工作。当在该模块外部调用它时,它不会。与此表单相关的所有功能都在文件 feedback.admin.inc 中,该文件已被包含在内,因此我不确定我缺少什么。

为了完整起见,我在下面包含了 feedback.admin.inc 的内容,以及它在我的登陆页面模块中的使用方式。有什么想法吗?谢谢。

feedback.admin.inc

<?php

function feedback_form($form, &$form_state) {

    $form = NULL;

    $form['first_name'] = array(
        '#type' => 'textfield',
        '#title' => 'First Name',
        '#required' => TRUE
    );

    $form['last_name'] = array(
        '#type' => 'textfield',
        '#title' => 'Last Name',
        '#required' => TRUE
    );

    $form['organization'] = array(
        '#type' => 'textfield',
        '#title' => 'Organization'
    );

    $form['email'] = array(
        '#type' => 'textfield',
        '#title' => 'Email',
        '#required' => TRUE
    );

    $form['telephone'] = array(
        '#type' => 'textfield',
        '#title' => 'Telephone',
        '#required' => TRUE
    );

    $form['comments'] = array(
        '#type' => 'textarea',
        '#title' => 'Comments',
        '#required' => TRUE
    );

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit Feedback',
        '#ajax' => array(
            'callback' => 'ajax_feedback_form_submit'
        )
    );

    return $form;
}

function ajax_feedback_form_submit($form, &$form_state) {

    if (count(form_get_errors())) {
        $response_text = '<ul>';

        ##
        ## Add each validation error to response text
        foreach(form_get_errors() as $element => $error) {
            $response_text .= "<li>$error</li>";            
        }

        $response_text .= '</ul>';
        $header_text = 'There are errors with your feedback.';
        $error_state = TRUE;

        ##
        ## Remove message data from session so user is not reminded a second time
        unset($_SESSION['messages']['error']);
        if (!count($_SESSION['messages'])) {
            unset($_SESSION['messages']);
        }

    } else {
        ##
        ## Prepare feedback data for insertion
        $data = array(
            'first_name' => $form_state['values']['first_name'],
            'last_name' => $form_state['values']['last_name'],
            'organization' => $form_state['values']['organization'],
            'email' => $form_state['values']['email'],
            'telephone' => $form_state['values']['telephone'],
            'comments' => $form_state['values']['comments'],
            'created' => time()
        );

        ##
        ## Insert feedback record
        drupal_write_record('feedback', $data);

        $response_text = "Your feedback has been received.";
        $header_text = 'Feedback Received';
        $error_state = FALSE;
    }

    ##
    ## Return AJAX response for interpretation by Drupal.ajax JavaScript object
    return array(
        '#type' => 'ajax', 
        '#commands' => array(
            array(
                'command' => 'modal',
                'text' => $response_text,
                'headerText' => $header_text,
                'errorState' => $error_state
            )
        )
    );
}

登陆页面

<?php module_load_include('inc', 'feedback', 'feedback.admin'); ?>

<div class="column">
    <?= render(drupal_get_form('feedback_form')) ?> 
</div>

I have a module in my Drupal 7 application called Feedback. It includes a form for submitting simple feedback. This form is submitted via AJAX, and I've already tested and verified the submission handling. In my feedback module, I had originally, via hook_menu, hard-coded the location of this form. I then decided that I wanted it to be more flexible - on a different content-type I have called Landing Page, a user may check a box to include the feedback form. When they do, I simply do a <?= render(drupal_get_form('feedback_form')); ?>, which pulls it in. The feedback form definition lives in a file called feedback.admin.inc, so I had to also put a <?php module_load_include('inc', 'feedback', 'feedback.admin'); ?> to get it to appear.

The form appears, but its AJAX handler is no longer working. Checking outgoing network traffic via Chrome, it appears that the AJAX request is being sent to the generic Drupal AJAX handler. So, when my function feedback_form is called within the feedback module, the form works correctly. When it's called outside that module, it does not. All of the functions related to this form are in the file feedback.admin.inc, which is being included, so I'm not sure what I'm missing.

For completeness, I've included the contents of feedback.admin.inc below, along with how it's being used in my Landing Page module. Any thoughts? Thanks.

feedback.admin.inc

<?php

function feedback_form($form, &$form_state) {

    $form = NULL;

    $form['first_name'] = array(
        '#type' => 'textfield',
        '#title' => 'First Name',
        '#required' => TRUE
    );

    $form['last_name'] = array(
        '#type' => 'textfield',
        '#title' => 'Last Name',
        '#required' => TRUE
    );

    $form['organization'] = array(
        '#type' => 'textfield',
        '#title' => 'Organization'
    );

    $form['email'] = array(
        '#type' => 'textfield',
        '#title' => 'Email',
        '#required' => TRUE
    );

    $form['telephone'] = array(
        '#type' => 'textfield',
        '#title' => 'Telephone',
        '#required' => TRUE
    );

    $form['comments'] = array(
        '#type' => 'textarea',
        '#title' => 'Comments',
        '#required' => TRUE
    );

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit Feedback',
        '#ajax' => array(
            'callback' => 'ajax_feedback_form_submit'
        )
    );

    return $form;
}

function ajax_feedback_form_submit($form, &$form_state) {

    if (count(form_get_errors())) {
        $response_text = '<ul>';

        ##
        ## Add each validation error to response text
        foreach(form_get_errors() as $element => $error) {
            $response_text .= "<li>$error</li>";            
        }

        $response_text .= '</ul>';
        $header_text = 'There are errors with your feedback.';
        $error_state = TRUE;

        ##
        ## Remove message data from session so user is not reminded a second time
        unset($_SESSION['messages']['error']);
        if (!count($_SESSION['messages'])) {
            unset($_SESSION['messages']);
        }

    } else {
        ##
        ## Prepare feedback data for insertion
        $data = array(
            'first_name' => $form_state['values']['first_name'],
            'last_name' => $form_state['values']['last_name'],
            'organization' => $form_state['values']['organization'],
            'email' => $form_state['values']['email'],
            'telephone' => $form_state['values']['telephone'],
            'comments' => $form_state['values']['comments'],
            'created' => time()
        );

        ##
        ## Insert feedback record
        drupal_write_record('feedback', $data);

        $response_text = "Your feedback has been received.";
        $header_text = 'Feedback Received';
        $error_state = FALSE;
    }

    ##
    ## Return AJAX response for interpretation by Drupal.ajax JavaScript object
    return array(
        '#type' => 'ajax', 
        '#commands' => array(
            array(
                'command' => 'modal',
                'text' => $response_text,
                'headerText' => $header_text,
                'errorState' => $error_state
            )
        )
    );
}

landing page

<?php module_load_include('inc', 'feedback', 'feedback.admin'); ?>

<div class="column">
    <?= render(drupal_get_form('feedback_form')) ?> 
</div>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人事已非 2025-01-03 11:14:47

表单提交发生在主题层调用之前,因此在模板文件中调用 module_load_include 为时已晚。另外,我非常确定在许多 AJAX 回调中根本不会调用主题层,因此包含永远不会运行。

您的表单函数需要位于 Drupal 可以在正常引导程序中找到它的某个位置,即在 .module 文件中,或者在 .module 文件中显式包含的文件中。我通常通过将 module_load_include 函数放在 .module 文件本身的开头来实现此目的。

Form submissions happen quite a bit before the theme layer is invoked so calling module_load_include in a template file is too late. Also I'm pretty sure in a lot of AJAX callbacks the theme layer isn't invoked at all so the include would never run.

Your form function needs to be somewhere Drupal can find it in a normal bootstrap, i.e. in a .module file, or a file explicitly included from a .module file. I normally do this by putting module_load_include functions at the beginning of the .module file itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文