首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >hook_form_alter()中的AJAX回调

问hook_form_alter()中的AJAX回调
EN

Drupal用户
提问于 2019-05-25 07:31:19
回答 2查看 5.5K关注 0票数 1

我不知道如何在hook_form_alter()中实现AJAX回调。

默认情况下,该字段为纯文本,并由客户端公司的NID (number)填充。模块名为"my_car“。我没有在这个字段中使用节点引用。

以下是代码:

代码语言:javascript
复制
function my_car_form_alter(&$form, &$form_state, $form_id) {

    if ($form_id == 'car_node_form') {

        $clientCompanies = companyTitle(12); // TID 12

        // Replace Client company NID with title
        $form['field_car_company']['und'][0]['value'] = array(
            '#title' => 'Client company',
            '#type' => 'select',
            '#default_value' => $form_state['node']->field_car_company['und'][0]['value'],
            '#options' => $clientCompanies,
            '#required' => TRUE,
            '#empty_option' => t('- Select -')
        );
    }
}

在这里,我使用companyTitle()函数返回所有具有TID 12的公司(节点),并将字段类型("textfield“替换为"select")及其内容--一个数字包含文本(NID和title)。

代码语言:javascript
复制
function companyTitle($tid) {

    $results = db_query("
        SELECT n.nid, n.title
        FROM {node} AS n
        LEFT JOIN {field_data_field_company_type} AS ct ON ct.entity_id = n.nid
        WHERE n.type = 'company' AND ct.field_company_type_tid = :tid
        ORDER BY n.title ASC",
        array(':tid' => $tid))->fetchAllKeyed();

    return $results;
}

我根据TID和title编写了返回客户公司NID和title的函数:

代码语言:javascript
复制
function ajaxCompanyTitle($tid, $companyName) {

    $query = db_select('node', 'company')
        ->fields('company', array('nid', 'title'))
        ->condition('company.type', 'company', '=')
        ->condition('type.field_company_type_tid', $tid, '=')
        ->condition('company.title', '%'.db_like($companyName).'%', 'LIKE')
        ->orderBy('company.title', 'ASC')
        ->range(0, 10);

    $query->leftJoin('field_data_field_company_type', 'type', 'type.entity_id = company.nid');

    $results = $query->execute()->fetchAll();

    return $results;
}

现在是如何用最后一个函数实现AJAX的问题。我需要文本字段(它不是一个选择列表)在AJAX搜索中,NID将作为标题呈现(NID仅保留在field_car_company_value列中的数据库中)。

显然,我不知道如何实现回调函数。

代码语言:javascript
复制
function my_car_form_alter(&$form, &$form_state, $form_id) {

    if ($form_id == 'car_node_form') {

        // Replace Client company NID with title
        $form['field_car_company']['und'][0]['value'] = array(
            '#title' => 'Client company',
            '#type' => 'textfield',
            '#required' => TRUE,
            '#ajax' => array(
                'callback' => 'ajax_callback',
                'wrapper' => 'edit-field-car-company-und-0-value',
            )
        );
    }
}

function ajax_callback($string = '') {

    $matches = array();

    if ($string) {

        $clientCompanies = ajaxCompanyTitle(12, $string);

        foreach ($clientCompanies as $clientCompany) {
            $matches[$clientCompany->title] = $clientCompany->title;
        }
    }

    drupal_json_output($matches);
}
EN

回答 2

Drupal用户

发布于 2019-05-26 01:04:58

Drupal中有两种类型的ajax。传统的AJAX,以及Drupal表单api #ajax。通过在表单中使用#ajax,但返回和AJAX响应,而不是#ajax回调响应,您将两者混合在一起。

要理解#ajax,您需要了解表单API的工作过程。这就是标准的非Ajax表单API表单在Drupal中的工作方式:

  1. 调用一些函数,它构建一个表示表单的呈现数组。
  2. 调用表单ALTER挂钩,允许其他模块/主题更改表单。
  3. Drupal缓存数据库中的呈现数组,以便在提交时进行比较,作为一种安全措施,以确保提交的数据与预期提交的数据类型匹配。
  4. 表单被呈现为HTML并发送到浏览器。
  5. 用户提交表单。
  6. Drupal从数据库中检索表单,确认允许提交的数据,并对其进行消毒。
  7. Drupal验证表单,运行提交钩子,并在表单提交后将用户重定向到他们应该在的任何页面。

在实现#ajax时,流程与上面相同,但中间有一些附加步骤。

  1. 调用一些函数,它构建一个表示表单的呈现数组。
  2. 调用表单ALTER挂钩,允许其他模块/主题更改表单。
  3. Drupal缓存数据库中的呈现数组,以便在提交时进行比较,作为一种安全措施,以确保提交的数据与预期提交的数据类型匹配。
  4. 表单被呈现为HTML并发送到浏览器。
  5. 用户做一些触发#ajax的事情
  6. 浏览器将表单中的所有数据发送回Drupal,就像表单已经提交一样。
  7. Drupal从数据库中检索表单,并确认允许提交的数据,并对其进行消毒。
  8. 将调用表单的验证和提交处理程序。必须将表单设置为在提交处理程序中重新构建ajax才能工作。
  9. 表单是从原始表单定义重新构建的,传递给它的是#ajax提交的值。
  10. 调用表单ALTER挂钩,允许其他模块使用#ajax提交的值修改表单。
  11. Drupal在数据库中缓存新的呈现数组,用于提交时的比较。
  12. ajax构建的表单将传递给#ajax回调处理程序。然后,处理程序返回表单中要注入到浏览器上的DOM中的部分。这可以是表单的一部分或全部。
  13. 新内容被插入到DOM中。
  14. 用户提交表单。
  15. Drupal从数据库中检索表单,确认允许提交的数据,并对其进行消毒。
  16. Drupal验证表单,运行提交钩子,并在表单提交后将用户重定向到他们应该在的任何页面。

参考您的代码,ajax回调将收到两个参数,$form和$form_state,并且需要返回表单的一部分。所以它应该看起来像:

代码语言:javascript
复制
function ajax_callback($form, $form_state) {
  return $form['some_element']['of_the_form'];
}

在您的表单中,这可能是$form['field_car_company']['und'][0]['value']。当表单最初以现在的方式呈现时,您将构建该表单元素的选项,如果表单是使用ajax提交的,则使用提交的值来确定要显示的新选项。

票数 2
EN

Drupal用户

发布于 2019-05-27 14:01:46

@Jaypan

我做了以下工作:

代码语言:javascript
复制
function my_car_menu() {

    $items = array();

    $items['car/autocomplete'] = array(
        'title' => 'Autocomplete for cars',
        'page callback' => 'car_autocomplete',
        'access arguments' => array('list of cars'),
        'type' => MENU_CALLBACK
    );

    return $items;
}

function my_car_form_alter(&$form, &$form_state, $form_id) {

    if ($form_id == 'car_node_form') {

        $form['field_car_company']['und'][0]['value']['#ajax'] = array(
            'callback' => 'ajax_callback'
        );

        $form['field_car_company']['und'][0]['value'] = array(
            '#type' => 'textfield',
            '#default_value' => $form_state['node']->field_car_company['und'][0]['value'],
            '#title' => 'Client company',
            '#description' => 'Zakupac',
            '#required' => TRUE,
            '#autocomplete_path' => 'car/autocomplete'
        );
    }
}

function ajax_callback($form, $form_state) {
    return $form['field_car_company']['und'][0]['value'];
}

function car_autocomplete($string = '') {

    $matches = array();

    if ($string) {

        $clientCompanies = ajaxCompanyTitle(12, $string);

        foreach ($clientCompanies as $clientCompany) {
            $matches[$clientCompany->title] = check_plain($clientCompany->title);
        }
    }

    drupal_json_output($matches);
}

AJAX回调现在起作用了。我已经用'#autocomplete_path' => 'car/autocomplete'实现了它。但是在数据库中现在写的是$clientCompany->title而不是$clientCompany->nid。我还需要数据库中的NID。

票数 0
EN
页面原文内容由Drupal提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://drupal.stackexchange.com/questions/281584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档