Dev to webs {Coding…}

เรียนรู้การพัฒนาซอฟเวอร์ เพื่อความรู้ที่ยั่งยืน

บทที่ 49: การสร้าง Dropdown Menu


1. ความเข้าใจเกี่ยวกับ Dropdown Menu

Dropdown Menu คือเมนูแบบเลื่อนลงที่ซ่อนอยู่และแสดงเมื่อผู้ใช้โต้ตอบ เช่น การคลิกหรือเลื่อนเมาส์

  • ใน Alpine.js สามารถสร้าง Dropdown ได้ง่ายด้วย x-show และ Transition
  • ใช้ร่วมกับ State เพื่อควบคุมการเปิด/ปิดเมนู

2. การสร้าง Dropdown Menu เบื้องต้น

ตัวอย่าง 1: Dropdown เปิด/ปิดด้วยการคลิก
<div x-data="{ isOpen: false }" class="relative inline-block">
    <!-- ปุ่มเปิด/ปิด Dropdown -->
    <button @click="isOpen = !isOpen" class="px-4 py-2 bg-blue-500 text-white rounded">
        Toggle Menu
    </button>

    <!-- Dropdown Menu -->
    <div 
        x-show="isOpen" 
        class="absolute mt-2 w-48 bg-white shadow-lg rounded border"
        @click.away="isOpen = false"
        x-transition>
        <ul>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 1</li>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 2</li>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 3</li>
        </ul>
    </div>
</div>

คำอธิบาย:

  • x-show="isOpen" ใช้ควบคุมการแสดง/ซ่อนเมนู
  • @click.away="isOpen = false" ปิดเมนูเมื่อคลิกนอกพื้นที่
  • x-transition เพิ่ม Animation ให้เมนู

3. การเพิ่ม Transition ใน Dropdown Menu

ตัวอย่าง 2: Dropdown พร้อม Animation
<div x-data="{ isOpen: false }" class="relative inline-block">
    <button @click="isOpen = !isOpen" class="px-4 py-2 bg-blue-500 text-white rounded">
        Toggle Menu
    </button>

    <div 
        x-show="isOpen" 
        class="absolute mt-2 w-48 bg-white shadow-lg rounded border"
        @click.away="isOpen = false"
        x-transition:enter="transition ease-out duration-300"
        x-transition:enter-start="opacity-0 transform scale-90"
        x-transition:enter-end="opacity-100 transform scale-100"
        x-transition:leave="transition ease-in duration-200"
        x-transition:leave-start="opacity-100 transform scale-100"
        x-transition:leave-end="opacity-0 transform scale-90">
        <ul>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 1</li>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 2</li>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 3</li>
        </ul>
    </div>
</div>

คำอธิบาย:

  • ใช้ x-transition เพิ่มเอฟเฟกต์การแสดงผลแบบ Fade และ Scale

4. การใช้ State ใน Dropdown Menu

ตัวอย่าง 3: Dropdown ที่เปลี่ยนข้อความตามตัวเลือก
<div x-data="{ isOpen: false, selected: 'Select an option' }" class="relative inline-block">
    <button @click="isOpen = !isOpen" class="px-4 py-2 bg-blue-500 text-white rounded">
        <span x-text="selected"></span>
    </button>

    <div 
        x-show="isOpen" 
        class="absolute mt-2 w-48 bg-white shadow-lg rounded border"
        @click.away="isOpen = false"
        x-transition>
        <ul>
            <li @click="selected = 'Option 1'; isOpen = false" class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 1</li>
            <li @click="selected = 'Option 2'; isOpen = false" class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 2</li>
            <li @click="selected = 'Option 3'; isOpen = false" class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Option 3</li>
        </ul>
    </div>
</div>

คำอธิบาย:

  • ใช้ State selected เพื่อเก็บค่าที่ผู้ใช้เลือก
  • อัปเดตข้อความในปุ่มเมื่อผู้ใช้เลือกตัวเลือก

5. การสร้าง Dropdown Menu แบบ Nested

ตัวอย่าง 4: Dropdown ซ้อนกัน
<div x-data="{ isOpen: false, subMenuOpen: false }" class="relative inline-block">
    <button @click="isOpen = !isOpen" class="px-4 py-2 bg-blue-500 text-white rounded">
        Toggle Menu
    </button>

    <div 
        x-show="isOpen" 
        class="absolute mt-2 w-48 bg-white shadow-lg rounded border"
        @click.away="isOpen = false"
        x-transition>
        <ul>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Main Option 1</li>
            <li 
                @click="subMenuOpen = !subMenuOpen" 
                class="px-4 py-2 hover:bg-gray-100 cursor-pointer relative">
                Main Option 2
                <div 
                    x-show="subMenuOpen" 
                    class="absolute left-full top-0 mt-0 ml-2 w-48 bg-white shadow-lg rounded border"
                    x-transition>
                    <ul>
                        <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Sub Option 1</li>
                        <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Sub Option 2</li>
                    </ul>
                </div>
            </li>
            <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer">Main Option 3</li>
        </ul>
    </div>
</div>

คำอธิบาย:

  • ใช้ State subMenuOpen ควบคุมการเปิด/ปิดเมนูย่อย
  • เมนูย่อยสามารถซ้อนอยู่ในเมนูหลักและเปิดเมื่อคลิก

6. การสร้าง Dropdown Menu แบบ Dynamic

ตัวอย่าง 5: Dropdown พร้อมข้อมูลจาก API
<div x-data="{ isOpen: false, options: [], fetchOptions() {
        fetch('https://jsonplaceholder.typicode.com/users')
            .then(response => response.json())
            .then(data => { this.options = data; });
    } }" x-init="fetchOptions" class="relative inline-block">
    <button @click="isOpen = !isOpen" class="px-4 py-2 bg-blue-500 text-white rounded">
        Toggle Menu
    </button>

    <div 
        x-show="isOpen" 
        class="absolute mt-2 w-48 bg-white shadow-lg rounded border"
        @click.away="isOpen = false"
        x-transition>
        <ul>
            <template x-for="option in options" :key="option.id">
                <li class="px-4 py-2 hover:bg-gray-100 cursor-pointer" x-text="option.name"></li>
            </template>
        </ul>
    </div>
</div>

คำอธิบาย:

  • ใช้ x-for เพื่อสร้างรายการใน Dropdown จากข้อมูล API
  • ข้อมูลในเมนูเปลี่ยนได้ตามคำตอบของ API

สรุป

ในบทนี้ คุณได้เรียนรู้การสร้าง Dropdown Menu ด้วย Alpine.js ตัวอย่างครอบคลุม Dropdown แบบพื้นฐาน, Dynamic Dropdown, Dropdown พร้อม Animation และเมนูย่อย การสร้าง Dropdown ด้วย Alpine.js ช่วยเพิ่มความสามารถในการโต้ตอบของเว็บไซต์ได้อย่างง่ายและมีประสิทธิภาพ!