รายการเลือกแบบไดนามิกในแบบฟอร์ม (ขึ้นอยู่กับรายการแบบหล่นลง)


28

ฉันใช้ Drupal เจ็ด ฉันต้องการให้ตัวเลือกในรายการที่เลือกขึ้นอยู่กับค่าที่เลือกในรายการเลือกอื่นในแบบฟอร์ม ฉันแน่ใจว่าสิ่งนี้เคยถูกถามมาหลายครั้งแล้ว แต่ฉันมีปัญหาในการหาคำตอบที่ชัดเจนสำหรับวิธีการทำสิ่งนี้

แบบฟอร์มมีไว้สำหรับผู้ใช้เพื่อป้อนประวัติการทำงาน พวกเขาจำเป็นต้องเลือกฝูงบินซึ่งเป็นโหนดที่อ้างอิงถึงประเภทฟิลด์ฝูงบินและนี่อยู่ในรายการดรอปดาวน์ อย่างไรก็ตามฝูงบินขึ้นอยู่กับรายการแบบดึงลงเมือง ผู้ใช้ต้องเลือกเมืองก่อนซึ่งจะกรองตัวเลือกสำหรับฝูงบิน ในประเภทเนื้อหาของฝูงบินฉันสร้าง taxonomy สำหรับเมืองที่ติดแท็กฝูงบิน

ฉันจะขอบคุณมากสำหรับพอยน์เตอร์ใด ๆ เกี่ยวกับวิธีที่ดีที่สุด (ง่ายที่สุด?) ที่จะไปเกี่ยวกับเรื่องนี้หรือสำหรับทรัพยากรที่มีประโยชน์ออนไลน์ซึ่งจะช่วย

คำตอบ:


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 ในรูปแบบ $ case

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

ตอนนี้เมื่อรายการ 'เลือกเมือง' เปลี่ยนไปมันจะสร้างส่วนห่อหุ้มฝูงบินของแบบฟอร์มใหม่ ค่า 'เมือง' ของคุณจะเป็น $ form_state ['values'] ดังนั้นเมื่อมีการสร้างแบบฟอร์มขึ้นใหม่เราจำเป็นต้องพิจารณาว่าตัวเลือกใดบ้างที่จะมอบให้กับรายการที่เลือกตามค่าของ 'เมือง'

// 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

อีกวิธีหนึ่งคุณสามารถทำเช่นนี้ในหลายขั้นตอน แต่ฉันไม่คิดว่าฟังดูเหมือนสิ่งที่คุณกำลังมองหา ยัง ^ โทรดี! โมดูลตัวอย่างนั้นยอดเยี่ยมสำหรับการเรียนรู้สิ่งนี้
jordojuice

@jordojuice ขอบคุณมากสำหรับคำตอบของคุณ ฉันกำลังทำอยู่ตอนนี้ ในตัวอย่างที่สามของรหัสที่คุณให้ไว้ข้างต้น (เริ่มต้น / รับค่า ... ) ฉันจะใช้ฟังก์ชันใดในส่วนนี้ของโค้ด มันไปในฟังก์ชั่น _ajax_callback หรือไม่? ขอบคุณ
เบ็น

ฉันติดตามโมดูลตัวอย่างสำหรับสิ่งนี้ แต่ฉันได้รับข้อผิดพลาดทุกครั้งที่ฉันเลือกรายการในรายการแบบหล่นลงแรก: คำเตือน: array_values ​​() คาดว่าพารามิเตอร์ 1 จะเป็นอาร์เรย์สตริงที่กำหนดใน _field_filter_items () (บรรทัด 525 ของ I: \ My Documents \ เว็บ \ XAMPP \ htdocs \ mysite \ โมดูล \ ข้อมูล \ field.module) ฉันกำลังใช้รูปแบบหลายขั้นตอนร่วมกับ ajax นี้ขึ้นอยู่กับแบบหล่นลงที่ฉันเขียนในโมดูลการแทนที่ที่กำหนดเอง .... แม้ว่าค่าที่ได้รับการเปลี่ยนแปลงสำหรับวันที่สองตามวันแรก มันเป็นเพียงการเตือนที่ปรากฏขึ้น แต่น่ารำคาญ ... ใครบางคนได้โปรดช่วยฉันลบคำเตือนนั้นได้ไหม ขอบคุณ!
ม.ค.

2 ความแตกต่างที่สำคัญระหว่างรหัสนี้และสิ่งใดที่ใช้งานได้กับ @Ben โปรดทราบว่า #suffix ใช้ ID และ ajax callback ส่งคืนองค์ประกอบของฟอร์มไม่ใช่ทั้งฟอร์ม นอกเหนือจากนี้มีประโยชน์มาก!
wolffer-east

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

@harshal - ฉันมีปัญหาเดียวกันและได้รับมันโดยใช้วิธีการแก้ปัญหาที่ฉันให้ในคำตอบของฉันโปรดดูด้านบน (altering form.inc) นี่เป็นบิตของการแฮ็ก แต่ใช้ได้สำหรับฉัน
เบ็น

@harshal - อาจเป็นทางออกที่ดีกว่านั่นคือ Hacker ด้านล่าง
Ben

1

ใส่บรรทัดของโค้ดเช่น
$nodes[''] = '- None -'; หลังจาก

 $nodes = array();

ใน ur 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

ใช้โมดูลจำกัด ตัวเลือกฟิลด์อ้างอิง

โมดูลนี้อนุญาตให้เขตข้อมูลอ้างอิงหลายประเภทมีตัวเลือกที่มีอยู่ของวิดเจ็ตที่ถูก จำกัด ด้วยค่าของเขตข้อมูลอื่นในเอนทิตีปัจจุบัน


มันเป็นทางเลือกให้กับโมดูลฟิลด์ตามเงื่อนไข?
Umair
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.