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


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.