Score:0

ส่งตัวกรองสัมผัสหนึ่งไปยังอีกอันหนึ่งหรือไม่ (D9)

ธง pk

ฉันมีฟิลด์สตริงประมาณโหลที่มีวัตถุและสถานะของพวกมัน (เช่น ใช้ 'AC_on' และ 'heater_off') และฉันมีมุมมองที่แสดงโหนดที่มีฟิลด์เหล่านั้น งานที่ฉันพยายามทำให้สำเร็จคือสิ่งนี้ ผู้ใช้ควรมีตัวเลือกสองชุดในการกรองโหนดตามฟิลด์ที่กล่าวถึงข้างต้น:

  • ในการเลือกวัตถุอย่างใดอย่างหนึ่งผ่านปุ่มตัวเลือก (AC หรือเครื่องทำความร้อน);
  • หากต้องการเลือกสถานะที่ตัวเลือกที่เลือกก่อนหน้านี้ควรอยู่ในชุดโหนดที่กรองแล้ว (เฉพาะ "เปิด" หรือเฉพาะ "ปิด" หรือ "เปิด" และ "ปิด" - ช่องทำเครื่องหมายที่เห็นได้ชัดเจน)

ไม่ใช่เรื่องใหญ่ที่จะสร้างตัวกรองที่ต้องการอย่างสวยงาม: เราสามารถใช้ตัวกรองช่องรวมสำหรับชุดปุ่มตัวเลือก (ค้นหาผ่านช่องวัตถุทั้งหมดและหากผู้ใช้เลือก "AC" ให้กรองค่า "AC_null" ทั้งหมดออก) และอีกครั้ง - สำหรับช่องทำเครื่องหมาย (สำหรับ "เปิด" ให้รวมค่าที่มี "เปิด" เป็นต้น) ปัญหาคือวิธีนี้ใช้ไม่ได้ :) ชุดที่สองไม่สนใจว่าวัตถุใดที่มีสถานะ "ปิด" จะกรองออก

ดังนั้น ฉันคิดว่าฉันสามารถส่งผ่านสิ่งที่ผู้ใช้เลือกในส่วนวิทยุ (AC) ไปยังค่าของตัวกรองช่องทำเครื่องหมายได้ (ดังนั้น มันจะไม่ค้นหาแค่ "เปิด" แต่ค้นหา "AC_on") ปัญหาคือสำหรับชีวิตของฉันฉันไม่สามารถหาโมดูลที่จะทำให้ฉันทำเช่นนั้นได้

"ดูตัวกรองที่ขึ้นต่อกัน" ดูเหมือนเป็นเพียงเครื่องมือสำหรับงาน แต่น่าเสียดาย ที่มีไว้สำหรับ D7 และฉันมี D9 มีวิธีใดบ้างที่จะบรรลุเป้าหมายนี้? ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชมอย่างสูง

ป.ล. ฉันไม่สามารถเขียนโค้ดได้ นอกเหนือจาก PHP one-liners และ CSS ที่ง่ายที่สุด ดังนั้นจึงควรใช้วิธีแก้ปัญหาแบบไม่ใช้โค้ด

misterdidi avatar
de flag
Hi, welcome to Drupal Answers. Maybe you should have a look at this tutorial https://bouteillenicolas.com/fr/blog-drupal/views-ajax-dynamic-dependent-exposed-filters. Although it's for D7, the logic behind remains the same for D9 (plus, hook_form_alter() still exists in D9). I'm afraid you can't escape a bit of custom code, though.
Basil Vlasyuk avatar
pk flag
Hi @misterdidi! Thank you. I've already made my peace that no-code solution doesn't exist in this case. I've created my own module, but what kills me is that, more often than not, the code solutions proposed for D8 don't work on D9 (and D7 solutions almost never work). So, their adaptaion requires the knowledge I lack. This article you've sent looks exactly like the thing I need, I'll check it and come back to tell if it worked. Thanks again!
Score:1
ธง pk

ขอขอบคุณ มิสเตอร์ดีดี้ ที่ทำให้ฉันเดินถูกทาง บทความที่คุณให้ไว้ช่วยได้ แต่เพื่อที่จะหาทางออก ฉันต้องศึกษาอีกสองสามสิบเรื่อง และในที่สุดทางออกก็มาถึง

ดังนั้นสำหรับงานนี้ ทางออกเดียวที่ฉันพบคือ:

  1. อ่านสิ่งที่อยู่ใน "ตัวกรองวิทยุ"
  2. แก้ไข "ตัวกรองช่องทำเครื่องหมาย" เพื่อให้มีค่าจาก "ตัวกรองวิทยุ" ในทุกตัวเลือก
  3. รวม "ฟิลด์สถานะ" ทั้งหมดลงในฟิลด์ที่มีหลายค่าหนึ่งฟิลด์ เพื่อให้เราสามารถ...
  4. ใช้ตัวกรองตามบริบทเพื่ออ่านค่า "ตัวกรองช่องทำเครื่องหมาย" จาก URL และค้นหาค่านั้นในฟิลด์หลายค่าของเรา

1. การอ่านค่าจาก Radio filter

ฉันทำสิ่งนี้สำเร็จด้วย views_pre_view ตะขอ:

ฟังก์ชัน MY_MODULE_views_pre_view($view, $display_id, array &$args) {  
  // ตรวจสอบว่าเป็นมุมมองและโหมดการแสดงผลที่ถูกต้องหรือไม่
  ถ้า ($view->id() == 'MY_VIEW') {
    สวิตช์ ($display_id) {
      กรณี 'MY_DISPLAY':
        // รับค่าใด ๆ ที่อยู่ใน Radio Filter และเขียนลงในตัวแปรส่วนกลาง
        $filter_input = $view->getExposedInput();
        ทั่วโลก $arg;
        $arg= $filter_input['RADIO_FILTER'];
    }
  }
}

(ในที่นี้และข้างหน้า ทุกอย่างใน CAPS คือชื่อที่คุณต้องแทนที่ด้วยชื่อที่คุณใช้)

ด้วยโค้ดนี้ ฉันอ่านสิ่งที่อยู่ใน Radio Filter และใส่ลงในตัวแปรส่วนกลาง $ หาเรื่อง.

2. ใส่ค่าจาก Radio Filter ลงใน Checkbox Filter

สำหรับส่วนนี้ฉันใช้ form_views_exposed_form_alter ตะขอ:

ฟังก์ชัน MY_MODULE_form_views_exposed_form_alter(&$form, $form_state, $form_id) {
  
  // เรียกตัวแปรส่วนกลางด้วยค่า Radio Filter
  ทั่วโลก $arg;
  
  // แปลงค่า RAW ของ Radio Filter เป็นสิ่งที่เราสามารถใช้สำหรับตัวกรองตามบริบท
  ถ้า ($arg == '1') {
    $arg= 'เอซี'; 
  }
  อื่น ($arg == '2') {
    $arg= 'ฮีตเตอร์'; 
  }
  อื่น ($arg == 'ทั้งหมด') {
    $arg= ''; 
  }
  
  $arg_on = ($arg . '_on');
  $arg_off = ($arg . '_off');
  
  // ตรวจสอบว่าเป็นรูปแบบที่ถูกต้อง
  ถ้า ($form['#id'] == 'EXPOSED_FILTER_FORM_ID') {
    
    // เราต้องการค่าตัวกรองที่แตกต่างกัน ขึ้นอยู่กับว่าค่าใน Radio Filter ถูกเลือกหรือตั้งค่าเป็นค่าเริ่มต้น ("ทั้งหมด")
    ถ้า ($arg != '') {
    $form['CHECKBOX_FILTER']['#options'] = อาร์เรย์(
      $arg_on => $arg_on,
      $arg_off => $arg_off,
      ); 
    }
    อื่น {
      $form['CHECKBOX_FILTER']['#options'] = อาร์เรย์(
      '_on' => '_on',
      '_off' => '_off', );
    }
    // ถ้าไม่มีอะไรถูกเลือก เราควรพิจารณาทุกอย่างที่เลือก
    ถ้า ($form['CHECKBOX_FILTER']['#value'] == '') {
      $form['CHECKBOX_FILTER']['#value'] = [$arg_on, $arg_off];
    }
  }
}

วิธีนี้จะทำให้ฉันแก้ไขค่าใน Checkbox Filter การทำเช่นนี้ทำให้ใช้งานไม่ได้มากเหมือนตัวกรองที่เปิดเผย (ฉันไม่แน่ใจว่าทำไม แต่ช่วงเวลาที่แก้ไขแบบฟอร์มผ่าน hook - มันไม่ได้กรองอะไรอีกต่อไป) แต่มีพารามิเตอร์ URL ซึ่งเราจะใช้สำหรับตัวกรองตามบริบท .

3. การรวมช่องพารามิเตอร์ทั้งหมดเป็นช่องเดียว

อันนี้เป็นสิ่งที่ฉันคาดว่าจะหาโมดูลได้ แต่ล้มเหลว ดังนั้น hook_entity_presave มันคือ.

ฟังก์ชัน MY_MODULE_entity_presave (Drupal\Core\Entity\EntityInterface $entity) {
  
  // ที่นี่เราเตรียมตัวแปรสำหรับทุกฟิลด์ที่เราจะต้องผสาน ...
  ถ้า ($entity->bundle() == 'MY_NODE_TYPE') {
    $par_ac = ($entity->field_AC_CHECK->value);
    $par_heater = ($entity->field_HEATER_CHECK->value);
    $par_all = ($par_ac . ',' . $par_heater);
  
    // ... และดูว่ามี "เปิด" หรือ "ปิด" อยู่หรือไม่ ...
    ถ้า (str_contains($par_all, 'เปิด')) {
      $par_cont_on = '_on';
    }
    ถ้า (str_contains($par_all, 'ปิด')) {
      $par_cont_off = '_off';
    }

    // ... เพื่อรวมทั้งหมดลงในฟิลด์เดียว และระบุค่า "เปิด" และ "ปิด" โดยรวมสำหรับกรณีที่ไม่ได้เติม Radio Filter
    $entity->field_par_comb = [$par_ac, $par_heater, $par_cont_on, $par_cont_off];
  }
}

ฉันไม่พอใจกับข้อเท็จจริงที่ว่าฟิลด์ถูกฮาร์ดโค้ดและไม่ได้รวบรวมแบบไดนามิก บางทีฉันอาจจะคิดหาวิธียกเลิกการฮาร์ดโค้ดเหล่านี้ในภายหลัง

แต่สำหรับตอนนี้ เรามีฟิลด์หลายค่าที่มีสถานะสำหรับทุกพารามิเตอร์ และในที่สุดเราก็สามารถ...

4. ใช้ตัวกรองตามบริบท

ตามที่เราพบในหน้า 2 ตัวกรองช่องทำเครื่องหมายที่เปิดเผยจะไม่ทำอะไรเลยเมื่อมีการแก้ไข แต่เราสามารถตรวจสอบพารามิเตอร์ URL ของตัวกรองช่องทำเครื่องหมายได้ ด้วยวิธีนี้ หากเรามี "checkbox_filter=heater_on" ตัวกรองตามบริบทจะดูในช่องที่มีหลายค่าจากหน้า 3 สำหรับค่า "heater_on"

เนื่องจากตัวกรองช่องทำเครื่องหมายสามารถมีค่าได้หลายค่า เราควรเลือก "OR" ร่วมกับค่าในการตั้งค่าของตัวกรอง

โปรดทราบว่าตัวกรองวิทยุควรเป็น "ไม่จำเป็น" เป็นเพราะเมื่อโหลดมุมมองเป็นครั้งแรก ค่าตัวกรองที่เปิดเผยเริ่มต้นจะไม่แสดงในพารามิเตอร์ URL ด้วยเหตุผลบางประการ แต่เนื่องจากค่า Radio Filter เริ่มต้นคือ "ใดๆ" (และเราควรซ่อนมันด้วย CSS ผ่าน :ลูกคนแรก ตัวเลือก) ในรหัสของเรามีส่วนที่คำนึงถึงกรณีนี้โดยการแทนที่ค่าตัวกรองวิทยุ "ทั้งหมด" ด้วย '' และเนื่องจากเรามีการตรวจสอบพิเศษและค่า "_on"/"_off" ในฟิลด์แบบหลายค่าของเรา จึงทำงานได้ดี:

  • หากเลือกค่าเริ่มต้น "ใดๆ" ในตัวกรองวิทยุ รหัสจะไม่แทนที่ค่าตัวกรองช่องทำเครื่องหมาย
  • ในการตั้งค่ามุมมอง ค่าตัวกรองช่องทำเครื่องหมายเริ่มต้นจะถูกตั้งค่าเป็น "_on" และ "_off" และตัวกรองสามารถทำงานได้
  • เมื่อผู้ใช้เลือก "AC", "Heater" หรือตัวเลือกอื่นๆ ใน Radio Filter ระบบจะใส่ค่านี้ลงในค่าตัวกรองช่องทำเครื่องหมายที่แก้ไขแล้วและตัวกรองตามบริบทจะเริ่มทำงาน

นี่เป็นกรณีที่แย่มากสำหรับประสบการณ์การพัฒนาโมดูล Drupal ครั้งแรก แต่ใช้งานได้อย่างไม่มีที่ติ ลูกค้ามีความสุข ฉันก็มีความสุข

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา