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

1.0.10 - Placeholder still not showing when using listbox in modal using dynamic options. #430

Open
marchampson opened this issue Oct 16, 2024 · 14 comments

Comments

@marchampson
Copy link

marchampson commented Oct 16, 2024

This is linked to #304 but I couldn't reopen:

Placeholder doesn't populate until you dropdown options, close modal and reopen.

I've updated to 1.0.10 but still experiencing the same issue. I have a very basic modal where the options are dynamically generated - normally I am pulling these in from the DB:

This is when you first launch the modal, I have pre-selected option: 2

Image

If you drop down, you can see 2 is highlighted:

Image

test-modal.blade.php:

<flux:modal name="test-modal" class="md:w-96 space-y-6">
    <div>
        <flux:heading size="lg">Test Modal</flux:heading>
    </div>
    {{ $industry }}
    <flux:select wire:model="industry" variant="listbox" placeholder="Choose industry..." searchable>
        <x-slot name="search">
            <flux:select.search placeholder="Search..."/>
        </x-slot>
       @foreach($industries as $key => $industry)
           <flux:option value="{{ $key }}">
               {{ $industry }}
           </flux:option>
         @endforeach
    </flux:select>
</flux:modal>

TestModal.php

<?php

namespace App\Livewire;

use Livewire\Attributes\On;
use Livewire\Component;

class TestModal extends Component
{
    public $industry = 2;
    public $industries = [];

    #[On('load-data')]
    public function loadData()
    {
        $this->industries = [
            '1' => 'Agriculture',
            '2' => 'Automotive',
            '3' => 'Banking',
        ];
    }

    public function render()
    {
        return view('livewire.test-modal');
    }
}

The button to launch is from a parent, the list view essentially and just shows the modal and fires the event:

public function showTestModal()
    {
        $this->dispatch('load-data')->to(\App\Livewire\TestModal::class);
        Flux::modal('test-modal')->show();
    }

I have a lot of these in my application, where there is a single modal on a parent list view and clicking on a row in a table, will launch the modal and run a method to load the data. All data loads, except for the placeholders.

Thanks.

@jeffchown
Copy link

jeffchown commented Oct 16, 2024

@marchampson I have been able to recreate the issue you describe.

Do the select options change often? If they're mainly data-driven with infrequent changes, could you load them in the mount() method to workaround this issue?

The other thing you could do, and is a pattern I use often, is to change your public array $industries property to a Computed property, e.g.:

#[Computed]
public function industries(): array
{
    return [
        '1' => 'Agriculture',
        '2' => 'Automotive',
        '3' => 'Banking',
    ];
}

and, you can then delete the loadData() method and simplify the showTestModal() method to:

public function showTestModal()
{
    Flux::modal('test-modal')->show();
}

then in your view:

@foreach($this->industries as $key => $industry)

I tried this approach with your code and it works on my end.

Another reason I like this approach is because I keep all of my dynamic data code in one predictable place and can reference it easily in the component and view without any duplication (and get to benefit from Livewire's computed property caching to boot!)

@marchampson
Copy link
Author

marchampson commented Oct 16, 2024

Hey @jeffchown thanks for looking into it.

In this instance, the values are dependant on the row you click, which opens the modal and populates the data. For example, a clients table. Click on the client, it opens the modal, loads the client data and this searchable dropdown is the client users so they can select an owner. I don't know the client until the row is clicked, so mount seems out of the equation.

I've tried the computed property route, when the 'load-data' event is picked up, in my actual component, it will set $this->client

#[On('load-client-data')]
    public function loadClientData($client_id)
    {
        if ($client_id) {
            $this->client = Team::find($client_id);
    ...

I then have a computed property:

 #[Computed]
    public function client_users()
    {
        return $this->client->users ?? [];
    }

Then I've swapped out the select to be:

<flux:select wire:model="defaultBoardsOwnerId" placeholder="Select user ..." variant="listbox" label="Default Board Owner" searchable>
                <x-slot name="search">
                    <flux:select.search placeholder="Search..."/>
                </x-slot>
                @foreach($this->client_users as $user)
                    <flux:option wire:key="board_user_{{ $user['id'] }}" value="{{ $user['id']}}">
                        {{ $user['name'] }}
                    </flux:option>
                @endforeach
            </flux:select>

Sadly, the same thing - no placeholder but the actual board owner is correctly ticked:

Image

However, if I could set the client in the mount(), I hardcoded to test, it does work as you say with the pattern above:

Image

But I'm not sure how I could do that if it's dynamically loading the client data?

@jeffchown
Copy link

@marchampson Ah, I see. Thanks for the extra context.

I have a similar pattern in one of my apps and use a very similar approach to the one you've shared here.
Mine works as expected, but my flux:select does not use variant="listbox".

Do all other inputs in your modal work, except the flux:select with variant="listbox"?

@marchampson
Copy link
Author

@jeffchown yes, if I convert to a basic select, it's fine.

However these lists can be rather long and I think once you have to scroll it's better to have a search. I used to use select2 but found there was so much code for those and you had to coax them along sometimes.

If this can be fixed then it's a game-changer for me. To be honest, Flux is already a game-changer, it's just this little niggle.

@jeffchown
Copy link

@marchampson Gotcha. I hear you re: select2 (and similar alternatives) and am hoping Flux will be able to replace a few similar js input libraries I've had to resort to in the past.

This discussion may have uncovered something I also have to account for in one of my apps.
Thanks for pointing this issue out and for the discussion.

Hopefully it will be a (relatively) easy for for @calebporzio and team.

@marchampson
Copy link
Author

@jeffchown Thanks for taking the time to investigate and offer suggestions! Hopefully this sheds some light and as you say, @calebporzio and team can work their magic.

@WorthLMS
Copy link

Following: Placeholder doesn't appear to be working at all with variant="listbox" even without doing anything...

I have static options set, and a default option with "" and nothing is pre-selected when I load a Modal

@marchampson
Copy link
Author

This is fixed for me in v1.0.14

Caleb just sent out a full list of all the fixed niggles that went into this release and this one fits the bill:

Show default selected value on lazy-loaded selects

Top work @calebporzio Thanks!

@marchampson
Copy link
Author

I may have been a bit hasty to close this. I'm seeing mixed results. @jeffchown how about you?

@marchampson marchampson reopened this Oct 19, 2024
@jeffchown
Copy link

@marchampson I haven't had any problems. But I'm curious to see if another issue's fix (#453 (comment)) might fix this issue for some people.

@marchampson
Copy link
Author

Thanks @jeffchown it still seems intermittent for me. Open a modal, the placeholder doesn't show, open a few more, nothing. Open the first one again, it shows and then from that moment, they all work.

@calebporzio
Copy link
Contributor

Thanks for this report and to others for the help!

Can someone provide ideally a single copy/pastable volt component? and if not, clearer instructions/code to reproduce with?

@marchampson
Copy link
Author

marchampson commented Oct 20, 2024 via email

@marchampson
Copy link
Author

OK, sorry @calebporzio this may be no help whatsoever. I've put the code from above into a Volt component, but haven't used Volt before. While the modal opens, the listbox doesn't. A standard select works, but hopefully you'll see what I've done wrong. Essentially though, I have a table view and a modal in a livewire component on the same view. When you click on a row, it should launch the modal and load in the data. The options do load, but it doesn't always load the placeholder, certainly not first time. If you click to another row and then back, it does:

<?php

use Flux\Flux;
use Livewire\Attributes\On;
use Livewire\Volt\Component;

new class extends Component {
    public $industry = 2;
    public $industries = [];

    public function showModal()
    {
        $this->dispatch('load-data')->self();
        Flux::modal('test-modal')->show();
    }

    #[On('load-data')]
    public function loadData()
    {
        $this->industries = [
            '1' => 'Agriculture',
            '2' => 'Automotive',
            '3' => 'Banking',
        ];
    }
}; ?>

<div xmlns:flux="http://www.w3.org/1999/html">
    <flux:button wire:click="showModal()">Test Modal</flux:button>

    <flux:modal name="test-modal" class="md:w-96 space-y-6 h-[300px]">
        <div>
            <flux:heading size="lg">Test</flux:heading>
        </div>
        <flux:select wire:model="industry" variant="listbox" placeholder="Choose industry..." searchable>
            <x-slot name="search">
                <flux:select.search placeholder="Search..."/>
            </x-slot>
            @foreach($industries as $key => $industry)
                <flux:option value="{{ $key }}">
                    {{ $industry }}
                </flux:option>
            @endforeach
        </flux:select>
    </flux:modal>
</div>

Thanks

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

4 participants