Search code examples
phplaraveltinymcealpine.js

Alpine Expression Error: can't access property "contains", $refs.panel is undefined


I'm using livewire and alpine to make a page with tabs. Every time a tab is clicked a different panel shows. Pretty straight forward however everytime i click a tab to change the panel I am getting this warning.

type hereAlpine Expression Error: can't access property "contains", $refs.panel is undefined

Expression: "! $refs.panel.contains($event.target) && close()"

 
<div class="relative" x-data="{\n            open: fal…       }\n            }" @keydown.escape.prevent.stop="close()" x-id="['dropdown-button']" @focusin.window="! $refs.panel.contains($event.target) && close()">

and this error

Uncaught TypeError: can't access property "contains", $refs.panel is undefined

I have tried explicitly defining where my live wire js in my app service provider

<header>
    <div class="bg-primaryBlack flex items-center justify-between px-8">
        <div>
            <a href="/">
                <x-application-logo class="w-28 h-24" />
            </a>
        </div>
        <div>
            <nav>
                <ul class="flex text-primaryWhite font-semibold">
                    <li class="mr-5">
                        <a
                            class="hover:text-gray-400 transition-colors ease-in-out"
                            href="#">Plaques</a>
                    </li>
                    <li class="mr-5">
                        <a
                            class="hover:text-gray-400 transition-colors ease-in-out"
                            href="#">Pens</a>
                    </li>
                    <li>
                        <a
                            class="hover:text-gray-400 transition-colors ease-in-out"
                            href="#">Lichtenberg</a>
                    </li>
                </ul>
            </nav>
        </div>
        {{--Parent--}}
        <div
            x-data="{
            open: false,
            toggle(){
                this.open = this.open ? this.close() : true
            },

            close(focusAfter){
                this.open=false

                focusAfter && focusAfter.focus()
            }
            }"
            @keydown.escape.prevent.stop="close()"
            x-id="['dropdown-button']"
            @focusin.window= "! $refs.panel.contains($event.target) && close()"
            class="relative">

            @if(Auth::user())
                <div class="flex items-center relative">
                    {{-- Button --}}
                    <button
                        x-ref="button"
                        @click="toggle()"
                        type="button"
                        :aria-expanded="open"
                        :aria-controls="$id('dropdown-button')"
                        class="text-primaryWhite text-sm block mr-2"
                        href="{{ route('dashboard') }}">{{ auth()->user()->name }}</button>
                    <x-icons.right-caret class="w-5 h-5 fill-primaryWhite" />
                    <div class="absolute top-0 -left-7">
                        <x-icons.cart class="w-5 h-5 fill-primaryWhite"/>
                        <a class="absolute -top-3 -left-5 text-xs bg-red-400 px-1.5 rounded-full text-primaryWhite font-bold" href="#">5</a>
                    </div>

                </div>
                {{--Panel--}}
                <div
                    x-ref="panel"
                    x-show="open"
                    @click.outside="close($refs.button)"
                    :id="$id('dropdown-button')"
                    style="display:none"
                    class="absolute top-10 right-3 z-10">
                    <ul class="bg-secondaryWhite px-4 text-left py-2 space-y-2 rounded uppercase text-sm">
                        <li class="hover:bg-primaryGreen hover:text-primaryWhite px-2 rounded">
                            <x-links.logout/>
                        </li>
                        <li class="hover:bg-primaryGreen hover:text-primaryWhite px-2 rounded">
                            <a href="{{ route('dashboard') }}">Dashboard</a>
                        </li>
                        <li class="hover:bg-primaryGreen hover:text-primaryWhite px-2 rounded">
                            <a href="#">Cart</a>
                        </li>
                    </ul>
                </div>

            @else
                <a
                    class="font-semibold text-gray-300 mr-4 hover:text-gray-400 transition-colors ease-in-out"
                    href="{{ route('login') }}">Login</a>
                <a
                    class="font-semibold text-gray-300 hover:text-gray-400 transition-colors ease-in-out"
                    href="{{ route('register') }}">Register</a>
            @endif
        </div>
    </div>
</header>

Solution

  • The <div> that contains x-ref="panel":

     <div
        x-ref="panel"
        x-show="open"
    .....
    

    is placed into an @if(Auth::user()) and in the @else branch there isn't any x-ref="panel", hence the error.

    To solve the problem you can create a new <div> into the @if(Auth::user()) check and move the x-data and all the Alpine stuff there.