Динамічний список вибору у формі (залежне спадне меню)


28

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

Форма призначена для користувачів ввести історію роботи. Їм потрібно вибрати ескадрилью, яка є посиланням вузла на тип поля ескадри, і це у випадаючому списку. Однак ескадра залежить від міського випадаючого списку. Спочатку користувачі повинні вибрати місто, яке відфільтрує варіанти ескадри. У типі вмісту ескадри я створив таксономію для міста, яка позначається ескадроном.

Я був би дуже вдячний за будь-які вказівки щодо найкращого способу (найпростішого?) Про це, або за будь-які корисні ресурси в Інтернеті, які допоможуть.

Відповіді:


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;
}

Тепер, коли список вибору "місто" зміниться, він відновить ескадронну обгорткову частину форми. Ваше значення "місто" тепер буде в $ form_state ['значення']. Отже, коли форма буде перебудована, нам потрібно визначити, які варіанти надати списку вибору, виходячи зі значення "місто".

// 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: \ Мої документи \ web \ xampp \ htdocs \ mysite \ module \ field \ field.module). Я використовую багатоетапну форму у поєднанні з цим залежним від аяксу, що я написав у користувальницькому модулі переосмислення .... Хоча значення змінюються для другого ДД на основі першого. Це лише попередження, яке з’являється, але дратує ... чи може хтось допомогти мені зняти це попередження? Спасибі!
січня 11

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

11

Велике спасибі jordojuice вище. З його допомогою мені вдалося знайти рішення. Я також посилався на приклад на веб-сайті http://public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submission . Я врешті-решт використав код, котрий нижче працював у спеціальному модулі. Чомусь я не зміг знайти жодного зі своїх значень у значенні $ form_state, але зміг знайти їх у $ формі. Нарешті, коли я тестував, я отримував повідомлення про помилку про те, що 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 - У мене була та сама проблема, і я вирішив її, реалізуючи рішення, яке я даю у своїй відповіді, будь ласка, дивіться вище (зміна 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 .

Після того як я видалив цей рядок, помилка зникла.


1

Використовуйте модуль обмеження параметрів поля Посилання

Цей модуль дозволяє довідкові поля декількох типів мати доступні параметри своїх віджетів обмеженими значеннями інших полів поточної сутності.


Це альтернатива модулю умовних полів?
Умаїр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.