表单中的动态选择列表(取决于下拉列表)


28

我正在使用Drupal七。我想使选择列表中的选项取决于表单中另一个选择列表中选择的值。我敢肯定这已经被问过很多次了,但是我很难找到一个明确的答案。

该表格供用户输入工作历史记录。他们需要选择一个中队,该中队是对中队字段类型的节点引用,并且在下拉列表中。但是,中队取决于城市的下拉列表。用户首先需要选择一个城市,然后将其过滤中队的选项。在中队内容类型中,我为城市创建了一个分类法,并将其标记为中队。

我将非常感谢您提供有关实现此目标的最佳方法(最简单的方法)的任何指示,或任何有帮助的在线有用资源。

Answers:


27

您可以使用Ajax完成此任务。Drupal 7现在具有良好的Ajax支持。在第一个选择列表(城市)上,您需要添加Ajax信息。然后,可以基于第一个选择列表中的信息填充第二个选择列表。您甚至还可以隐藏第二个选择列表,直到第一个选择列表中的一个选项被选中为止,我将稍作解释。首先,设置基本形式:

$form['city'] = array(
  '#type' => 'select',
  '#title' => t('City'),
  '#options' => $options,
  '#ajax' => array(
    'event' => 'change',
    'wrapper' => 'squadron-wrapper',
    'callback' => 'mymodule_ajax_callback',
    'method' => 'replace',
  ),
);
$form['squadron_wrapper'] = array('#prefix' => '<div class="squadron-wrapper">', '#suffix' => '</div>');
$form['squadron_wrapper']['squadron'] = array(
  '#type' => 'select',
  '#title' => t('Squadron'),
  '#options' => $squadron_options,
);

这只是元素的基本设置。现在,您需要一种方法来确定中队应该使用的选项。首先,您需要在“ city”选择列表中标识您的Ajax回调。在大多数情况下,您可以只返回包装ajax元素的元素,在这种情况下为$ form。

function mymodule_ajax_callback($form, $form_state) {
  return $form;
}

现在,当“城市”选择列表更改时,它将重建表单的中队包装器部分。您的“城市”值现在将在$ form_state ['values']中。因此,在重建表单时,我们需要基于“ city”的值确定为选择列表提供哪些选项。

// Get the value of the 'city' field.
$city = isset($form_state['values']['city']) ? $form_state['values']['city'] : 'default';
switch ($city) {
  case 'default':
    // Set default options.
    break;
  case 'losangeles':
    // Set up $squadron_options for los angeles.
    break;
}

// If you want to hide the squadron select list until a city is
// selected then you can do another conditional.
if ($city !== 'default') {
  $form['squadron_wrapper']['squadron'] = array(
    '#type' => 'select',
    '#title' => t('Squadron'),
    '#options' => $squadron_options,
  );
}

6
可以在“示例”模块中找到示例(“ AJAX示例”→“从属下拉列表”)。您也可以在“ 层次选择”模块中看到。
kalabro 2011年

顺便说一句,您也可以以多步骤形式进行此操作,但是我认为这听起来并不像您想要的那样。还^好电话!示例模块非常适合学习此类内容。
jordojuice

@jordojuice非常感谢您的回答。我正在努力。在上面给出的代码的第三个示例中(//开始获取值...),我要将代码的这一部分放在哪个函数中?它是否包含在_ajax_callback函数中?谢谢

我按照示例模块进行操作,但是每次在第一个下拉列表中选择一个项目时都会出错:警告:array_values()期望参数1为数组,在_field_filter_items()中给出的字符串(I:\ My Documents的第525行) \ web \ xampp \ htdocs \ mysite \ modules \ field \ field.module)。我将多步表单与我在自定义覆盖模块中编写的依赖于ajax的下拉列表结合使用。尽管这只是一个警告,但令人讨厌……有人可以帮助我删除该警告吗?谢谢!

2此代码与@Ben最终使用的代码之间的重要区别。注意,#suffix使用一个id,而ajax回调返回form元素,而不是整个表单。除此之外,这超级有帮助!
wolffer-east

11

非常感谢上面的jordojuice。在他的帮助下,我设法找到了解决方案。我还参考了http://public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submission中的示例。我最终使用下面的代码在自定义模块中工作。由于某种原因,我无法在$ form_state值中找到任何值,但能够在$ form中找到它们。最终,当我进行测试时,我收到一条错误消息,表明Drupal在下拉菜单中检测到非法选择。我通过在form.inc中注释掉第1290行来解决这个问题:

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));

我使用的最终代码是:

<?php

function sappers_squadron_form_work_history_node_form_alter(&$form, &$form_state) {     
        //echo '<pre>';
        //print_r ($form);
        //echo '</pre>';

        $squadron_options = array();

        if(isset($form['field_wkhist_city']['und']['#default_value'][0])) {
            $city = $form['field_wkhist_city']['und']['#default_value'][0];
        }
        else {
            $city = 0;
        }

        $squadron_options = sappers_squadron_squadrons($city);

        $form['field_wkhist_city']['und']['#ajax'] = array(
            'event' => 'change',
            'wrapper' => 'squadron-wrapper',
            'callback' => 'sappers_squadron_ajax_callback',
            'method' => 'replace',
        );

        $form['field_squadron']['und']['#prefix'] = '<div id="squadron-wrapper">';
        $form['field_squadron']['und']['#suffix'] = '</div>';
        $form['field_squadron']['und']['#options'] = $squadron_options;
}


function sappers_squadron_ajax_callback($form, $form_state) {   
    $city = $form['field_wkhist_city']['und']['#value'];

    $form['field_squadron']['und']['#options'] = sappers_squadron_squadrons($city);

    return $form['field_squadron'];
}


function sappers_squadron_squadrons($city) {
    $nodes = array();

    $select = db_query("SELECT node.title AS node_title, node.nid AS nid FROM  {node} node INNER JOIN {taxonomy_index} taxonomy_index ON node.nid = taxonomy_index.nid WHERE (( (node.status = '1') AND (node.type IN  ('squadron')) AND (taxonomy_index.tid = $city) )) ORDER BY node_title ASC");

    $nodes[]="";

    foreach ($select as $node) {
            $nodes[$node->nid] = $node->node_title;
    }

    return $nodes;
}

?>

我得到一个非法选择。请联系网站管理员。我尝试实现以上错误。你能帮忙吗?
严厉的

@harshal-我遇到了同样的问题,并通过实施我在回答中给出的解决方案来解决该问题,请参见上文(更改form.inc)。这有点hack,但对我有用。
2016年

@harshal-可能更好的解决方案是下面的Hacker提供的解决方案。
2016年

1

把代码行,即
$nodes[''] = '- None -'; 之后

 $nodes = array();

sappers_squadron_squadrons function 您那里,这将解决您的错误

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.