Skip to content

Select input + Islands + infinite scroll broken #2483

@cstisa

Description

@cstisa

Hi everyone,

I was trying to create a select input using Flux and Livewire v4 (islands) in order to create an infinite scroll down inside a <flux:select>

The most I can do without having any issues in the console is this :

<flux:select class="max-w-sm h-10!" wire:model="selectedCompanyId">
    @island(name: 'companies')
        @foreach ($this->companies as $company)
            <flux:select.option value="{{ $company->id }}" wire:key="company-{{ $company->id }}">
                {{ $company->name }}
            </flux:select.option>
        @endforeach
    @endisland
    @if ($this->companies->hasMorePages())
        <flux:select.option value="" wire:click="loadMoreCompanies" wire:island.append="companies">
            Load more ...
        </flux:select.option>
    @endif
</flux:select>

And in the component class :

    public $selectedCompanyId;

    public int $companiesPage = 1;

    #[Computed]
    public function companies(): LengthAwarePaginator
    {
        $this->authorize('viewAny', Company::class);

        return Company::orderBy('name')
            ->paginate(
                perPage: 5,
                columns: ['id', 'name'],
                pageName: 'companiesPage',
                page: $this->companiesPage
            );

    }

    public bool $isLoadingCompanies = false;

    public function loadMoreCompanies(): void
    {
        if ($this->isLoadingCompanies || ! $this->companies->hasMorePages()) {
            return;
        }

        $this->isLoadingCompanies = true;
        $this->companiesPage++;
        $this->isLoadingCompanies = false;
    }

I have two major problems :

  1. When clicking on the last select option to load more, the select closes itself and it doesn't have the attribute keep-open like in the <flux:dropdown> which prevent the menu to close itself when doing a click

  2. I can't set the <flux:select> a fixed number of items to show in order to keep having only 5 items visible in the frame, then having to scroll down in order to load more automatically with something like wire:intersect for example

Does anyone have any idea on how to solve my problems?

Edit 1 :

I'll add that I tried the same thing with <flux:dropdown>

<flux:dropdown>
    <flux:button icon:trailing="chevron-down">Company</flux:button>

    <flux:menu>
        <flux:menu.radio.group wire:model.live="selectedCompanyId">

            @island(name: 'companies')
                @foreach ($this->companies as $company)
                    <flux:menu.radio  wire:key="company-{{ $company->id }}">{{ $company->name }}</flux:menu.radio>
                @endforeach
            @endisland

            @if ($this->companies->hasMorePages())
                <flux:menu.radio keep-open wire:click="loadMoreCompanies" wire:island.append="companies">
                    Load more</flux:menu.radio>
            @endif

        </flux:menu.radio.group>
    </flux:menu>
</flux:dropdown>

It kind of works, even if for a form, I'd rather have a <flux:select> input but the other problem is that I get a console error each time I click the load more button :

Uncaught DOMException: Operation is not supported

Edit 2 :

I manage to make it work using only HTML (but it is ugly):

<select id="company" name="company" size="5" wire:model.live="selectedCompanyId">
    @island(name: 'companies')
        @foreach ($this->companies as $company)
            <option value="{{ $company->id }}" wire:key="company-{{ $company->id }}">{{ $company->name }}
            </option>
        @endforeach
    @endisland

    @if ($this->companies->hasMorePages())
        <option disabled value="" wire:intersect.full="loadMoreCompanies" wire:island.append="companies">
            Load more ...
        </option>
    @endif
</select>

Edit 4 :

I tried with <flux:select variant="combobox"> and it almost works except for two problems :

  1. I can't select any option
  2. I still get the console error : Uncaught DOMException: Operation is not supported
        <flux:select variant="combobox">
            <x-slot name="input">
                <flux:input :filter="false" placeholder="Filter companies..."
                    wire:model.live.debounce.300ms="companyFilter" />
            </x-slot>

            @island(name: 'companies', always: true)
                @foreach ($this->companies as $company)
                    <flux:select.option value="{{ $company->id }}" wire:key="company-{{ $company->id }}">
                        {{ $company->name }}</flux:select.option>
                @endforeach
            @endisland

            <flux:select.option disabled wire:intersect.full="loadMoreCompanies" wire:island.append="companies">
                Load more</flux:select.option>
        </flux:select>

Originally posted by @cstisa in #2481

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions