Динамический список выбора в форме (зависимый выпадающий список)


28

Я использую Drupal 7. Я хочу, чтобы параметры в списке выбора зависели от значения, выбранного в другом списке выбора в форме. Я уверен, что об этом уже много раз спрашивали, но мне сложно найти четкий ответ, как это сделать.

Форма для пользователей, чтобы ввести историю работы. Им нужно выбрать эскадрилью, которая является ссылкой узла на тип поля эскадрильи, и это в раскрывающемся списке. Однако эскадрилья зависит от выпадающего списка города. Сначала пользователям необходимо выбрать город, который затем отфильтрует параметры для эскадрильи. В типе контента эскадрильи я создал таксономию для города, которая помечается для эскадрильи.

Я был бы очень благодарен за любые указания относительно лучшего (самого простого?) Пути для этого или за любые полезные ресурсы онлайн, которые могли бы помочь.

Ответы:


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,
);

Это просто базовая настройка элементов. Теперь вам нужен способ, чтобы определить, какие варианты должны идти в эскадрилье. Для начала вам нужно сделать так, чтобы ваш обратный вызов Ajax был идентифицирован в списке выбора города. В большинстве случаев вы можете просто вернуть элемент, который оборачивает элемент ajax, в нашем случае это $ form.

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

Теперь, когда список выбора 'city' изменится, он перестроит часть формы, относящуюся к эскадрилье. Ваше значение 'city' теперь будет в $ 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» → «Зависимый выпадающий список»). Вы также можете увидеть в модуле иерархического выбора .
Калабро

Кстати, в качестве альтернативы вы можете сделать это в многошаговой форме, но я не думаю, что это звучит так, как вы искали. Также ^ хороший звонок! Примеры модулей отлично подходят для изучения такого рода вещей.
jordojuice

@jordojuice Большое спасибо за ваш ответ. Я работаю над этим сейчас. В третьем примере кода, который вы даете выше (начало // Получить значение ...), в какую функцию я помещаю эту часть кода? Это входит в функцию _ajax_callback? Спасибо
Бен

Я следовал примеру модуля для этого, но каждый раз, когда я выбираю элемент в первом раскрывающемся списке, я получаю сообщение об ошибке: Предупреждение: array_values ​​() ожидает, что параметр 1 будет массивом, строка задана в _field_filter_items () (строка 525 из I: \ My Documents \ Web \ XAMPP \ HTDOCS \ MySite \ модули \ поле \ field.module). Я использую многошаговую форму в сочетании с этим ajax-зависимым раскрывающимся списком, который я написал в пользовательском модуле переопределения .... Хотя значения меняются для второго dd на основе первого. Хотя это просто предупреждение, но раздражает ... может кто-нибудь помочь мне снять это предупреждение? Благодарность!
Январь

2 Важные различия между этим кодом и тем, что в итоге заработало для @Ben. Обратите внимание, что #suffix использует идентификатор, а обратный вызов ajax возвращает элемент формы, а не всю форму. Кроме этого это было очень полезно!
Вольфер-Восток

11

Большое спасибо Jordojuice выше. С его помощью мне удалось найти решение. Я также сослался на пример на http://public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submission . В конце концов я использовал приведенный ниже код, который работал в пользовательском модуле. По какой-то причине я не смог найти ни одно из своих значений в значениях $ form_state, но смог найти их в $ form. Наконец, когда я тестировал, я получал сообщение об ошибке, что Drupal обнаружил неправильный выбор в раскрывающемся списке. Я обошел это, закомментировав строку 1290 в form.inc:

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

@harshal - у меня была та же проблема, и я обошел ее, реализовав решение, которое я дал в своем ответе, см. выше (изменение form.inc). Это что-то вроде хака, но у меня это сработало.
Бен

@harshal - Вероятно, лучшее решение - это решение, данное Хакером ниже.
Бен

1

поставить строку кода т.е.
$nodes[''] = '- None -'; после

 $nodes = array();

в ур, sappers_squadron_squadrons function и это решит вашу ошибку

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


1

Основная причина: «Обнаружен неправильный выбор. Пожалуйста, свяжитесь с администратором сайта». является то, что пустая строка с добавленным значением 0 $nodes[]="";недопустима для поля field_squadron.

См. Предварительное программирование и разработка PHP , но имейте в виду, что DANGEROUS_SKIP_CHECK и проверенные флаги в D7 устарели .

После того, как я удалил эту строку, ошибка исчезла.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.