0

I have created a recursive category display using Livewire 3.x and AlpineJS 3.x The categories are stored in the database. Everything is working except for the activeDropdown function. When I open a parent category and click on a child category inside it, the parent category does not remain open.

How can I solve this so that it stays open?

Thank you.

Source code:

resources\views\livewire\category-navigation.blade.php

<div x-data="sidebar" class="sidebar z-50 transition-all duration-300">
    <div class="bg-white">
        <ul class="p-4 py-0" x-data="{ activeDropdown: null }">
        @foreach ($categories as $category)
            @if ($category->children->count() > 0)
                <li class="nav-item">
                    <ul>
                        <li class="nav-item">
                            <button type="button" class="nav-link group"
                            :class="{ 'active': activeDropdown === '{{ $category->slug }}' }"
                                @click="activeDropdown === '{{ $category->slug }}' ? activeDropdown = null : activeDropdown = '{{ $category->slug }}'">
                                <div class="flex items-center">
                                    <span class="text-black">
                                        {{ $category->name }}
                                    </span>
                                </div>
                                <div class="" :class="{ '!rotate-90': activeDropdown === '{{ $category->slug }}' }">
                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
                                        xmlns="http://www.w3.org/2000/svg">
                                        <path d="M9 5L15 12L9 19" stroke="currentColor" stroke-width="1.5"
                                            stroke-linecap="round" stroke-linejoin="round" />
                                    </svg>
                                </div>
                            </button>
                            <ul x-cloak x-show="activeDropdown === '{{ $category->slug }}'" x-collapse class="sub-menu text-gray-500" @click.away="activeDropdown = null" @click.stop>
                                @foreach ($category->children as $child)
                                    @include('livewire.category-item', ['category' => $child])
                                @endforeach
                            </ul>
                        </li>
                    </ul>
                </li>
            @else
                <li class="nav-item">
                    <a href="{{ url($category->full_path) }}" wire:click.prevent="navigateToCategory('{{ $category->full_path }}')" class="nav-link group"
                        :class="{ 'active': '{{ request()->routeIs("products.byCategory") && request()->route("slug") == $category->slug ? "active" : "" }}'}">
                        <div class="flex items-center">
                            <span class="text-black">{{ $category->name }} ({{ $category->products()->count() }})</span>
                        </div>
                    </a>
                </li>
            @endif
        @endforeach
        </ul>
    </div>
</div>

resources\views\livewire\category-item.blade.php

@if ($category->children->count() > 0)
    <li x-data="{ subActive: null }">
        <button type="button"
            class="before:bg-gray-300 before:w-[5px] before:h-[5px] before:rounded before:mr-2 hover:bg-gray-100"
            :class="{ 'active': subActive === '{{ $category->slug }}' }"
            @click.stop="subActive === '{{ $category->id }}' ? subActive = null : subActive = '{{ $category->slug }}'">

            {{ $category->name }}

            <div class="ml-auto" :class="{ '!rotate-90': subActive === '{{ $category->slug }}' }">
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
                    xmlns="http://www.w3.org/2000/svg">
                    <path d="M9 5L15 12L9 19" stroke="currentColor" stroke-width="1.5"
                        stroke-linecap="round" stroke-linejoin="round" />
                </svg>
            </div>
        </button>
        <ul class="sub-menu text-gray-500 ml-4" x-show="subActive === '{{ $category->slug }}'" x-collapse>
            @foreach ($category->children as $child)
                @include('livewire.category-item', ['category' => $child]) <!-- REKURZÍV hívás -->
            @endforeach
        </ul>
    </li>
@else
    <li>
        <a href="{{ url($category->full_path) }}" wire:click.prevent="navigateToCategory('{{ $category->full_path }}')">{{ $category->name }} ({{ $category->products()->count() }})</a>
    </li>
@endif

Js code:

document.addEventListener("alpine:init", () => {
    Alpine.data("sidebar", () => ({
        init() {
            const selector = document.querySelector('.sidebar ul a[href="' + window.location.href + '"]');
            if (selector) {
                selector.classList.add('active');
                const ul = selector.closest('ul.sub-menu');
                if (ul) {
                    let ele = ul.closest('li.menu').querySelectorAll('.nav-link');
                    if (ele) {
                        ele = ele[0];
                        setTimeout(() => {
                            ele.click();
                        });
                    }
                }
            }
        },
    }));
});
4
  • You should show the navigateToCategory() method to make it clear what happens when you click on an element Commented Mar 13 at 1:39
  • ` <?php namespace App\Livewire; use Livewire\Component; use App\Models\Category; class CategoryNavigation extends Component { public function navigateToCategory($fullPath) { return redirect($fullPath); } } ` Commented Mar 13 at 19:34
  • Probably you must use window.location.href instead of window.location.pathname to initialize the const selector. I can't find any ul with class menu in your code, so ul.closest('li.menu') returns null: please fix your code (edit the question instead of adding comments containing code) Commented Mar 14 at 2:37
  • I have fixed the post. Now it works so that the parent category stays open. However, at the second level, it closes again. Any ideas on that? I need to traverse the levels recursively. Commented Mar 14 at 10:36

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.