Danh sách chọn động trong biểu mẫu (thả xuống phụ thuộc)


28

Tôi đang sử dụng Drupal seven. Tôi muốn làm cho các tùy chọn trong danh sách chọn phụ thuộc vào giá trị được chọn trong danh sách chọn khác trong một biểu mẫu. Tôi chắc chắn rằng điều này đã được hỏi nhiều lần trước đây, nhưng tôi gặp khó khăn trong việc tìm câu trả lời rõ ràng cho cách thực hiện việc này.

Biểu mẫu dành cho người dùng nhập lịch sử công việc. Họ cần chọn một phi đội là một tham chiếu nút cho loại trường phi đội và đây là một danh sách thả xuống. Tuy nhiên, phi đội, phụ thuộc vào danh sách thả xuống của thành phố. Người dùng trước tiên cần chọn một thành phố sau đó sẽ lọc các tùy chọn cho phi đội. Trong loại nội dung của phi đội, tôi đã tạo một phân loại cho thành phố được gắn thẻ vào phi đội.

Tôi sẽ rất biết ơn bất kỳ con trỏ nào về cách tốt nhất (đơn giản nhất?) Để thực hiện điều này, hoặc cho bất kỳ tài nguyên hữu ích trực tuyến nào có thể giúp ích.

Câu trả lời:


27

Bạn có thể sử dụng Ajax để thực hiện điều này. Drupal 7 có hỗ trợ Ajax tốt ngay bây giờ. Trên danh sách chọn đầu tiên (thành phố), bạn sẽ cần thêm thông tin Ajax. Sau đó, danh sách chọn thứ hai có thể được điền dựa trên thông tin trong danh sách đầu tiên. Bạn thậm chí có thể ẩn danh sách chọn thứ hai cho đến khi một tùy chọn trong mục đầu tiên được chọn và tôi sẽ giải thích cách thực hiện điều đó trong một lát. Đầu tiên, để thiết lập các hình thức cơ bản:

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

Đây chỉ là thiết lập cơ bản của các yếu tố. Bây giờ bạn sẽ cần một cách để xác định những tùy chọn nào nên đi trong phi đội. Trước tiên, bạn cần làm cho cuộc gọi lại Ajax của bạn được xác định trong danh sách chọn 'thành phố'. Trong hầu hết các trường hợp, bạn chỉ có thể trả về phần tử bao bọc phần tử ajax, trong trường hợp này là $ form.

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

Bây giờ, khi danh sách chọn 'thành phố' thay đổi, nó sẽ xây dựng lại phần bao bọc phi đội của biểu mẫu. Giá trị 'thành phố' của bạn bây giờ sẽ ở $ form_state ['value']. Vì vậy, khi biểu mẫu được xây dựng lại, chúng ta cần xác định những tùy chọn nào sẽ cung cấp cho danh sách chọn dựa trên giá trị của 'thành phố'.

// 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
Có thể tìm thấy các ví dụ trong mô-đun Ví dụ ("Ví dụ AJAX" → "thả xuống phụ thuộc"). Bạn cũng có thể thấy tại mô-đun Chọn phân cấp .
kalabro

Nhân tiện, thay vào đó, bạn có thể làm điều này ở dạng nhiều bước, nhưng tôi không nghĩ rằng nó nghe giống như những gì bạn đang tìm kiếm. Cũng ^ gọi tốt! Các mô-đun ví dụ là tuyệt vời để học loại điều này.
jordojuice

@jordojuice Cảm ơn bạn rất nhiều vì câu trả lời của bạn. Tôi đang làm việc trên nó bây giờ. Trong ví dụ thứ ba về mã bạn đưa ra ở trên (bắt đầu // Lấy giá trị ...) tôi sẽ đặt phần nào của mã này vào? Nó có hoạt động trong hàm _ajax_callback không? Cảm ơn
Ben

Tôi đã theo mô-đun ví dụ cho việc này nhưng tôi gặp lỗi mỗi lần tôi chọn một mục trong lần thả xuống đầu tiên: Cảnh báo: Array_values ​​() dự kiến ​​tham số 1 sẽ là mảng, chuỗi được đưa ra trong _field_filter_items () (dòng 525 của I: \ My Documents \ web \ xampp \ htdocs \ mysite \ module \ field \ field.module). Tôi đang sử dụng một hình thức nhiều bước kết hợp với trình đơn phụ thuộc ajax này mà tôi đã viết trong một mô-đun ghi đè tùy chỉnh .... Mặc dù các giá trị được thay đổi cho dd thứ hai dựa trên lần đầu tiên. Đó chỉ là một cảnh báo xuất hiện nhưng gây khó chịu ... ai đó có thể vui lòng giúp tôi xóa cảnh báo đó không? cảm ơn!
Tháng Một

2 Sự khác biệt quan trọng giữa mã này và những gì đã kết thúc làm việc cho @Ben. Lưu ý rằng #suffix sử dụng id và hàm gọi lại ajax trả về phần tử biểu mẫu, không phải toàn bộ biểu mẫu. Khác hơn là điều này là siêu hữu ích!
wolffer-đông

11

Rất cám ơn jordojuice ở trên. Với sự giúp đỡ của anh ấy, tôi đã tìm được giải pháp. Tôi cũng đã tham khảo ví dụ tại http://public-action.org/content/drupal-7-form-api-deperee-lists-and-ajax-form-submission . Cuối cùng tôi đã sử dụng mã dưới đây hoạt động trong một mô-đun tùy chỉnh. Vì một số lý do, tôi không thể tìm thấy bất kỳ giá trị nào của mình trong các giá trị $ form_state, nhưng có thể tìm thấy chúng ở dạng $. Cuối cùng, khi tôi kiểm tra, tôi nhận được thông báo lỗi rằng Drupal đã phát hiện ra sự lựa chọn bất hợp pháp trong trình đơn thả xuống. Tôi đã làm tròn điều này bằng cách bình luận dòng 1290 trong form.inc:

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

Mã cuối cùng tôi sử dụng là:

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

?>

Tôi nhận được một sự lựa chọn bất hợp pháp đã được phát hiện. Vui lòng liên hệ với quản lý. lỗi khi tôi cố gắng thực hiện ở trên. Bạn có thể giúp không?
khắc nghiệt

@harshal - Tôi đã có cùng một vấn đề và giải quyết nó bằng cách thực hiện giải pháp tôi đưa ra trong câu trả lời của mình, vui lòng xem ở trên (thay đổi form.inc). Đây là một chút hack nhưng nó làm việc cho tôi.
Ben

@harshal - Có lẽ một giải pháp tốt hơn là một giải pháp được đưa ra bởi Hacker dưới đây.
Ben

1

đặt dòng mã tức là
$nodes[''] = '- None -'; sau

 $nodes = array();

trong ur sappers_squadron_squadrons function và điều đó sẽ giải quyết lỗi của bạn

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


1

Nguyên nhân sâu xa của "Một lựa chọn bất hợp pháp đã được phát hiện. Vui lòng liên hệ với quản trị viên trang web." là chuỗi rỗng có giá trị 0 được thêm bởi $nodes[]="";không hợp lệ cho trường field_squadron.

Xem Lập trình và phát triển PHP nâng cao , nhưng hãy nhớ rằng DANGEROUS_SKIP_CHECK và các cờ được xác thực không được dùng trong D7 .

Sau khi tôi xóa dòng đó, lỗi đã biến mất.


1

Sử dụng mô-đun giới hạn tùy chọn trường Tham chiếu

Mô-đun này cho phép các trường tham chiếu của một số loại có các tùy chọn khả dụng của widget bị giới hạn bởi các giá trị của các trường khác trong thực thể hiện tại.


Nó có phải là một thay thế cho mô-đun trường có điều kiện?
Umair
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.