วิธีการ เติมข้อมูลใหม่ใน HTML Select Options
โดยไม่ก่อให้เกิดเหตุการณ์เปลี่ยนแปลงด้วย jQuery
เมื่อทำงานกับหลาย ๆ องค์ประกอบ HTML select ในเว็บแอปพลิเคชัน คุณอาจพบว่าตัวเลือกใน dropdown หนึ่งมีผลต่อทางเลือกที่มีอยู่ในอีกตัวเลือกหนึ่ง สถานการณ์ทั่วไปคือการทำให้ตัวเลือกที่มีอยู่ใน select หนึ่งหายไปเมื่อถูกเลือกในอีกตัวเลือกหนึ่ง อย่างไรก็ตาม การทำเช่นนี้อาจทำให้เหตุการณ์การเปลี่ยนแปลงถูกกระตุ้นโดยไม่ตั้งใจ ซึ่งสามารถทำให้ตรรกะของคุณซับซ้อนได้ ในโพสต์นี้เราจะพูดถึงวิธีการเติมข้อมูลใหม่ในตัวเลือกแบบดึงข้อมูลได้โดยไม่ทำให้เกิดเหตุการณ์ที่ไม่พึงประสงค์เมื่อใช้ jQuery
ปัญหา
ลองนึกภาพว่าคุณมี dropdown สองตัว (องค์ประกอบ select) ที่มีความสัมพันธ์ซึ่งกันและกัน คุณต้องการสร้างระบบที่การเลือกตัวเลือกใน dropdown หนึ่งจะลบตัวเลือกนั้นออกจาก dropdown ที่สอง โดยมั่นใจว่าผู้ใช้ไม่สามารถเลือกตัวเลือกเดียวกันจากทั้งสองตัวเลือกได้ อย่างไรก็ตาม ตามพฤติกรรมของ jQuery เริ่มต้น การเปลี่ยนตัวเลือกในหนึ่ง select ยังเรียกเหตุการณ์การเปลี่ยนแปลงสำหรับ select นั้น ซึ่งอาจนำไปสู่พฤติกรรมที่ไม่คาดคิดในแอปพลิเคชันของคุณ
ตัวอย่างสถานการณ์
นี่คือโครงสร้าง HTML ที่ง่ายเพื่อแสดงตัวเลือก dropdown:
<select id="one">
<option value="1">หนึ่ง</option>
<option value="2">สอง</option>
<option value="3">สาม</option>
</select>
<select id="two">
<option value="1">หนึ่ง</option>
<option value="2">สอง</option>
<option value="3">สาม</option>
</select>
เมื่อคุณเลือก “หนึ่ง” จาก dropdown แรก (#one
) เป้าหมายคือการลบ “หนึ่ง” จาก dropdown ที่สอง (#two
) ถ้าคุณเลือก “สอง” จาก #two
พฤติกรรมเดียวกันควรเกิดขึ้นในทางกลับกัน
วิธีแก้ปัญหา
เพื่อหลีกเลี่ยงการเรียกเหตุการณ์การเปลี่ยนแปลงในขณะที่เติมข้อมูลใหม่ในตัวเลือกของคุณ คุณจะต้องใช้วิธีการสองขั้นตอน: ตัดการเชื่อมต่ออีเวนต์แฮนเดอร์ชั่วคราว และ ใช้ธง เพื่อกำหนดว่าสิ่งใดควรรับเหตุการณ์การเปลี่ยนแปลงหรือไม่
ขั้นตอนที่ 1: ดัดแปลงตรรกะ JavaScript
เริ่มโดยการตั้งค่าฟังก์ชัน jQuery ของคุณดังนี้:
$(function () {
var $one = $("#one");
var $two = $("#two");
var selectOptions = [
$("option", $one).clone(),
$("option", $two).clone()
];
var isChanging = false; // ธงเพื่อป้องกันการเรียกเหตุการณ์การเปลี่ยนแปลง
$one.change(function () {
if (isChanging) return; // ข้ามถ้ากำลังเปลี่ยนอยู่
isChanging = true; // ตั้งธงก่อนเปลี่ยนตัวเลือก
var selectedValue = $("option:selected", this).val();
$two.find("option[value='" + selectedValue + "']").remove();
repopulateOptions($two, selectOptions[1]); // คืนตัวเลือก
isChanging = false; // รีเซ็ตธง
});
$two.change(function () {
if (isChanging) return; // ข้ามถ้ากำลังเปลี่ยนอยู่
isChanging = true; // ตั้งธงก่อนเปลี่ยนตัวเลือก
var selectedValue = $("option:selected", this).val();
$one.find("option[value='" + selectedValue + "']").remove();
repopulateOptions($one, selectOptions[0]); // คืนตัวเลือก
isChanging = false; // รีเซ็ตธง
});
function repopulateOptions($select, options) {
options.each(function() {
if (!$select.find("option[value='" + this.value + "']").length) {
$select.append(this); // เพิ่มเฉพาะถ้ายังไม่มีอยู่แล้ว
}
});
}
});
ขั้นตอนที่ 2: การอธิบายส่วนสำคัญ
- ธง isChanging: ธง boolean นี้ใช้ติดตามว่าควรดำเนินการอีเวนต์แฮนเดอร์หรือไม่เพื่อป้องกันไม่ให้เกิดเหตุการณ์ที่ไม่ตั้งใจในระหว่างการจัดการตัวเลือก
- ฟังก์ชัน Repopulate: ฟังก์ชันนี้ช่วยให้ปรับปรุงการซิงค์ของ select โดยการคืนตัวเลือกที่เคยมีอยู่ เพื่อให้ผู้ใช้มีทางเลือกทั้งหมดที่เข้าถึงได้ เว้นแต่จะถูกเลือกแล้วใน dropdown อื่น
- การโคลนตัวเลือก: การโคลนตัวเลือกเดิมช่วยให้เรามีการอ้างอิงถึงทางเลือกทั้งหมดที่มีอยู่ ซึ่งทำให้ง่ายต่อการจัดการสิ่งที่จะแสดง
สรุป
การจัดการตัวเลือกที่มีความสัมพันธ์ซึ่งกันและกันอาจเป็นเรื่องซับซ้อน โดยเฉพาะอย่างยิ่งเมื่อมุ่งหวังที่จะหลีกเลี่ยงการเรียกเหตุการณ์ที่ไม่พึงประสงค์ โดยการปฏิบัติตามแนวทางในโพสต์นี้ คุณสามารถสร้างประสบการณ์ผู้ใช้ที่ไร้รอยต่อซึ่งตัวเลือกจะถูกปรับให้เหมาะสมในเวลาจริงโดยไม่มีปัญหาที่เกี่ยวข้องจากการก่อให้เกิดเหตุการณ์ วิธีแก้ปัญหานี้ไม่เพียงแต่ปกป้องจากพฤติกรรมที่ไม่คาดคิด แต่ยังทำให้ตัวเลือกของคุณชัดเจนและผู้ใช้มั่นใจได้อีกด้วย!
หากคุณมีคำถามหรือประสบการณ์ที่ต้องการแชร์เกี่ยวกับ jQuery และ dropdown แบบพลศาสตร์ โปรดคอมเมนต์ด้านล่างได้เลย!