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

Custom component to wrap flux:select multiple doesn't render flux:options properly #678

Open
jeffchown opened this issue Nov 14, 2024 · 4 comments

Comments

@jeffchown
Copy link

jeffchown commented Nov 14, 2024

Hi all,

@calebporzio This might not be an issue but instead my not understanding the order in which Blade interpolation occurs (or something along those lines).

In order to make my code more concise when using the new flux:select multiple functionality, I have created a custom component that 'wraps' flux:select. My component is as follows:

resources/views/components/multiselect.blade.php

<flux:select
    variant="listbox"
    multiple
    indicator="checkbox"
    {{ $attributes }}
>
    {{ $slot }}
</flux:select>

So I can call it in my views via <x-multiselect ... />

When I use my new component, the flux:options do not render properly (obvious because the styling doesn't match a normal flux:option), nor are they selectable.

For example, if in my view I have:

<div class="space-y-4">
    <flux:select variant="listbox" multiple placeholder="Choose industries..." label="via flux:select">
        <flux:option>Photography</flux:option>
        <flux:option>Design services</flux:option>
        <flux:option>Web development</flux:option>
        <flux:option>Accounting</flux:option>
        <flux:option>Legal services</flux:option>
        <flux:option>Consulting</flux:option>
        <flux:option>Other</flux:option>
    </flux:select>

    <x-multiselect placeholder="Choose industries..." label="via x-multiselect">
        <flux:option>Photography</flux:option>
        <flux:option>Design services</flux:option>
        <flux:option>Web development</flux:option>
        <flux:option>Accounting</flux:option>
        <flux:option>Legal services</flux:option>
        <flux:option>Consulting</flux:option>
        <flux:option>Other</flux:option>
    </x-multiselect>
</div>

For the first 'native' flux:select, the options render and work properly to show:
Image

but the 2nd select, using my x-multiselect component does not render the options properly, and they are not selectable:
Image

Inspecting the results in devtools shows multiple differences in the code generated by the examples above - most notably, no ui-options are in the markup for the 2nd select.

There may be something I'm missing or do not understand, but I'd really like to figure this one out as it will help me greatly simplify my code for some very complex forms that use many multiple select inputs.

Thanks in advance for any help/insights!

@ju5t
Copy link

ju5t commented Nov 14, 2024

That's weird, we do this with every Flux component and haven't seen this before. We even do multi inheritance if that's a word/thing. I haven't got much time this evening but will tinker a bit tomorrow morning to see if I can replicate this.

@jeffchown
Copy link
Author

@ju5t Agreed. I've wrapped other Flux components without issue.
The flux:select variants are definitely more complex, but I'm hoping to find a way to do this.

Thanks! Here's hoping we can get this working.

@jeffchown
Copy link
Author

jeffchown commented Nov 16, 2024

UPDATE: It seems the issue is the flux:options in my custom x-multiselect are not picking up the $variant via the @aware([ 'variant', 'indicator' ]) directive in the option.blade.php file.

Therefore, the $variant prop is null and then $custom === false causing the file to render it as a 'standard' option thus breaking the Flux functionality.

Now the trick is to figure out why the @aware isn't aware ;)

UPDATE: Of course, it is in the Laravel docs:

The @aware directive cannot access parent data that is not explicitly passed to the parent component via HTML attributes. Default @props values that are not explicitly passed to the parent component cannot be accessed by the @aware directive

So, given the above, how can I 'wrap' the flux:select multiple in a way that I don't have to pass the variant and indicator explicitly to my custom component each time? (which was one thing I was trying to streamline)

I'm essentially trying to reduce this e.g.:

<flux:select
    wire:model="form.city_ids"
    variant="listbox"
    multiple
    indicator="checkbox"
    searchable
    label="Cities"
    placeholder="Choose Cities..."
>

to this:

<x-multiselect
    wire:model="form.city_ids"
    label="Cities"
    placeholder="Choose Cities..."
>

as I have a lot of multiselects in some large forms so I want to keep my code concise and consistent, and I want to make it easy for me to make global changes to all of the multiselects by editing the one custom component blade file (vs. having to change each multiselect separately)

@calebporzio Your insight(s) here would be much appreciated.

@jeffchown
Copy link
Author

jeffchown commented Nov 16, 2024

Because of the way @aware works, the quickest way to accomplish what I want and 'get to green' for now seems to be to create two wrapping custom components, one for flux:select and one for flux:option.

views/components/multiselect.blade.php

@props([
    'variant' => 'listbox',
    'multiple' => true,
    'indicator' => 'checkbox',
])

<flux:select
    :variant="$variant"
    :multiple="$multiple"
    :indicator="$indicator"
    {{ $attributes }}
>
    {{ $slot }}
</flux:select>

views/components/multioption.blade.php

@aware([
    'variant' => 'listbox',
    'indicator' => 'checkbox',
])

<flux:option :variant="$variant" :indicator="$indicator" {{ $attributes }}>
    {{ $slot }}
</flux:option>

Then, I can use the components in my forms via e.g.:

<x-multiselect wire:model="industries" placeholder="Choose more industries...">
    <x-multioption>Photography</x-multioption>
    <x-multioption>Design services</x-multioption>
    <x-multioption>Web development</x-multioption>
    <x-multioption>Accounting</x-multioption>
    <x-multioption>Legal services</x-multioption>
    <x-multioption>Consulting</x-multioption>
    <x-multioption>Other</x-multioption>
</x-multiselect>

While this works, I'm open to feedback/ideas :)

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

2 participants