Livewire组件表单提交后动态生成的下拉菜单消失(Alpine.js v2.8环境)
Livewire组件表单提交后动态生成的下拉菜单消失(Alpine.js v2.8环境)
我正在开发一个带多选下拉菜单的Laravel Livewire组件,下拉选项是用JavaScript动态生成的,但提交表单后,下拉选项就消失了。
下面是下拉菜单的核心HTML代码:
<div id="dropdown" style="display: none;" class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" wire:ignore.self> <!-- Dynamically generated options will go here --> </div>
问题的核心限制是:我没法配合@livewireScripts使用最新版的Alpine.js,因为我依赖的一个库已经内置了Alpine v2.8,而且这个库的代码是混写在一起的,没办法单独提取出需要的Alpine代码。
表单提交前一切功能正常,但一旦提交表单、Livewire组件完成刷新,下拉菜单就会消失。
完整的前端代码如下:
HTML部分
<div class="relative"> <label class="block text-sm mb-1" for="roles">Mention roles</label> <div class="mt-1 relative"> <button type="button" id="toggleDropdown" class="relative w-full bg-white border border-gray-200 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary sm:text-sm"> <span id="displayText" class="block truncate">Select roles</span> <span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"> <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </span> </button> <div id="dropdown" style="display: none;" class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" wire:ignore.self> <!-- Dynamically generated options will go here --> </div> </div> </div> <input type="hidden" id="selectedRoles" wire:model="selectedRoles">
JavaScript部分
let isDropdownInitialized = false; // Flag to track if dropdown is initialized function initializeDropdown(roles) { console.log('Initializing dropdown with roles:', roles); // Debug: Check roles passed to the function const selectedRolesInput = document.getElementById('selectedRoles'); const toggleDropdownButton = document.getElementById('toggleDropdown'); const dropdown = document.getElementById('dropdown'); const displayText = document.getElementById('displayText'); const dropdownContainer = document.querySelector('.relative'); let selectedOptions = []; // Function to create dropdown items function createDropdownItems() { console.log('Creating dropdown items'); // Debug: Track when dropdown items are created dropdown.innerHTML = ''; // Clear previous dropdown items roles.forEach(role => { console.log('Creating item for role:', role); // Debug: Track each role being added const div = document.createElement('div'); div.classList.add('cursor-pointer', 'select-none', 'relative', 'py-2', 'pl-3', 'pr-9', 'hover:bg-primary', 'hover:text-white'); div.setAttribute('data-role-id', role.id); div.addEventListener('click', function(event) { console.log('Role clicked:', role); // Debug: Track role selection event.stopPropagation(); toggleOption(role); }); const span = document.createElement('span'); span.textContent = role.name; span.classList.add('block', 'truncate'); const checkIcon = document.createElement('span'); checkIcon.classList.add('absolute', 'inset-y-0', 'right-0', 'flex', 'items-center', 'pr-4', 'text-primary'); checkIcon.style.display = selectedOptions.some(selected => selected.id === role.id) ? 'block' : 'none'; const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('class', 'h-5 w-5'); svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); svg.setAttribute('viewBox', '0 0 20 20'); svg.setAttribute('fill', 'currentColor'); const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute('fill-rule', 'evenodd'); path.setAttribute('d', 'M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z' ); path.setAttribute('clip-rule', 'evenodd'); svg.appendChild(path); checkIcon.appendChild(svg); div.appendChild(span); div.appendChild(checkIcon); dropdown.appendChild(div); }); } // Toggle the dropdown visibility toggleDropdownButton.addEventListener('click', function(event) { console.log('Dropdown toggle clicked'); // Debug: Track toggle button click event.stopPropagation(); dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none'; }); // Toggle selection of a role function toggleOption(role) { console.log('Toggling selection for role:', role); // Debug: Track role selection toggle const index = selectedOptions.findIndex(selected => selected.id === role.id); if (index !== -1) { selectedOptions.splice(index, 1); } else { selectedOptions.push(role); } updateDisplayText(); createDropdownItems(); updateSelectedRolesInput(); } // Update the displayed text of selected roles function updateDisplayText() { console.log('Updating display text with selected options:', selectedOptions); // Debug: Track selected options displayText.textContent = selectedOptions.length ? selectedOptions.map(option => option.name) .join(', ') : 'Select roles'; } // Update the hidden input field with selected roles function updateSelectedRolesInput() { const selectedIds = selectedOptions.map(option => option.id).join(','); selectedRolesInput.value = selectedIds; selectedRolesInput.dispatchEvent(new Event('input')); console.log('Updated selected roles input:', selectedIds); // Debug: Track updated input value } // Initialize the dropdown items createDropdownItems(); // Close the dropdown if clicked outside document.addEventListener('click', function(event) { if (!dropdownContainer.contains(event.target) && dropdown.style.display === 'block') { console.log('Closing dropdown (clicked outside)'); // Debug: Track dropdown close action dropdown.style.display = 'none'; } }); } document.addEventListener('livewire:initialized', () => { @this.on('send-message', (data) => { // 原代码此处console内容不完整,保留现有结构 }); });
备注:内容来源于stack exchange,提问作者Tillie
相关产品推荐
相关产品推荐

