Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation Item Current Attribute dropped on dispatched event. #918

Open
3 tasks done
kyledoesdev opened this issue Dec 22, 2024 · 8 comments
Open
3 tasks done

Navigation Item Current Attribute dropped on dispatched event. #918

kyledoesdev opened this issue Dec 22, 2024 · 8 comments

Comments

@kyledoesdev
Copy link

Flux version

1.1

Livewire version

3.5.17

What is the problem?

When an event is dispatched from a component to another component, the :current Attribute on a navigation item seems to drop off. Attached is a demo video of this happening.

2024-12-22.12-09-03.mp4

Code snippets

Attached are the files involved with this issue:

Navigation Badge Livewire Component

<?php

namespace App\Livewire\Invites;

use App\Models\Invite;
use Livewire\Attributes\Computed;
use Livewire\Attributes\On;
use Livewire\Component;

class NavigationBadge extends Component
{
    public function render()
    {
        return view('livewire.invites.navigation-badge');
    }

    #[Computed]
    #[On('invitation-updated')]
    public function invitations()
    {
        return Invite::getPending();
    }
}

Navigation Component Template

<div>
    <flux:navbar.item
        href="{{ route('invites') }}"
        :badge="$this->invitations"
        badge-color="sky"
        icon="envelope" 
        :current="request()->is('invites')"
    >
        Invitations
    </flux:navbar.item>
</div>

Model getPending query function.

public static function getPending(): int
  {
      return self::query()->where('user_id', auth()->id())->where('status', self::PENDING)->count();
  }

Navigation Layout Header.

<flux:header container>
    <flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />

    <flux:navbar class="-mb-px max-lg:hidden">
        <flux:navbar.item icon="home" href="{{ route('welcome') }}" :current="request()->is('/')">
            Home
        </flux:navbar.item>

        @auth
            <flux:navbar.item icon="adjustments-horizontal" href="{{ route('dashboard') }}" :current="request()->is('dashboard')">
                Dashboard
            </flux:navbar.item>

            <livewire:invites.navigation-badge />
        @endauth

    </flux:navbar>

    <flux:spacer />

    <flux:button x-on:click="$flux.dark = ! $flux.dark" icon="moon" variant="subtle" aria-label="Toggle dark mode" />

    @auth
    
        <flux:dropdown position="top" align="start">
            <flux:profile avatar="{{ auth()->user()->avatar }}" />

            <flux:menu>
                <flux:menu.item icon="arrow-right-start-on-rectangle" wire:click="logout">
                    Logout
                </flux:menu.item>
            </flux:menu>
        </flux:dropdown>
    @else
        <flux:button size="sm" class="mx-1" href="{{ route('twitch.login') }}" icon-trailing="arrow-up-right">Login</flux:button>
    @endauth
</flux:header>

Invite approved function that dispatches event:

public function update($inviteId, $status)
  {
      $this->form->update($inviteId, $status);

      $this->dispatch('invitation-updated');
  }

How do you expect it to work?

I expect it to when the event is dispatched, the count of the badge in the navigation item to be updated without the theming underline disappearing. The current route did not change.

Please confirm (incomplete submissions will not be addressed)

  • I have provided easy and step-by-step instructions to reproduce the bug.
  • I have provided code samples as text and NOT images.
  • I understand my bug report will be closed if I haven't met the criteria above.
@jeffchown
Copy link

jeffchown commented Dec 22, 2024

@kyledoesdev That's happening because your navigation item is a Livewire component containing the event listener thus it is getting re-rendered when the event is dispatched and, at that point, the route is livewire/update so the navbar.item's route does not match.

I believe if you move the navbar.item markup outside of the component, and refactor the component to only render the flux:badge, all will work as you expect, e.g.:

layout-level:

<flux:navbar.item
    href="{{ route('invites') }}"
    icon="envelope" 
    :current="request()->is('invites')"
>
    Invitations <livewire:navigation-badge />
</flux:navbar.item>

livewire/navigation-badge.blade.php

<flux:badge color="sky">{{ $this->invitations }}</flux:badge>

@kyledoesdev
Copy link
Author

@kyledoesdev That's happening because your navigation item is a Livewire component containing the event listener thus it is getting re-rendered when the event is dispatched and, at that point, the route is livewire/update so the navbar.item's route does not match.

I believe if you move the navbar.item markup outside of the component, and refactor the component to only render the flux:badge, all will work as you expect, e.g.:

layout-level:

<flux:navbar.item
    href="{{ route('invites') }}"
    icon="envelope" 
    :current="request()->is('invites')"
>
    Invitations <livewire:navigation-badge />
</flux:navbar.item>

livewire/navigation-badge.blade.php

<flux:badge color="sky">{{ $this->invitations }}</flux:badge>

This somewhat patches the problem, but the badge is now not included in the accent underline of the nav item because it's a sperate badge being rendered. This works, it just doesn't have that fluid look to it:

Image

@jeffchown
Copy link

@kyledoesdev We're getting closer... I'll give this a think.

@kyledoesdev
Copy link
Author

@kyledoesdev We're getting closer... I'll give this a think.

Sounds good, I am going to continue to tinker with it as well.

@jeffchown
Copy link

@kyledoesdev Just heading out, but what about moving the word 'Invitations' into the component's render so the component is responsible for the entire menu prompt?

@kyledoesdev
Copy link
Author

@kyledoesdev Just heading out, but what about moving the word 'Invitations' into the component's render so the component is responsible for the entire menu prompt?

I think that'll do it. I can throw some tailwind on the badge to scale it better. But I can go with this one for now:

2024-12-22.12-52-21.mp4

@joshhanley
Copy link
Member

@kyledoesdev thanks for reporting! @jeffchown is correct, on update, request has changed, so the current route no longer matches. Caleb recently added wire:current to Livewire to solve this problem when using Livewire directly. But that won't work with Flux's navbars.

So even if you manage to find a work around, I think you should leave this open, so we can see if we can get Flux using something like wire:current so you don't need the work around.

@kyledoesdev
Copy link
Author

@kyledoesdev thanks for reporting! @jeffchown is correct, on update, request has changed, so the current route no longer matches. Caleb recently added wire:current to Livewire to solve this problem when using Livewire directly. But that won't work with Flux's navbars.

So even if you manage to find a work around, I think you should leave this open, so we can see if we can get Flux using something like wire:current so you don't need the work around.

Sounds good Josh! Let's leave it open for now. The work-around that @jeffchown suggested above is working fine for now for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants