protonemedia / laravel-splade

💫 The magic of Inertia.js with the simplicity of Blade 💫 - Splade provides a super easy way to build Single Page Applications (SPA) using standard Laravel Blade templates, and sparkle it to make it interactive. All without ever leaving Blade.
https://splade.dev
MIT License
1.47k stars 111 forks source link

Question: how to prevent the dynamic Remote URL from making ajax calls on page load #482

Closed thecyrilcril closed 1 year ago

thecyrilcril commented 1 year ago

Description:

I have this setup

                <x-splade-select name="country_code"
                    label="Select your country"
                    :options="$countries"
                    placeholder="Select your country..."
                    choices
                />

               <x-splade-select name="city_name"
                    label="Select your city"
                    remote-url="`/country/cities/${form.country_code}`"
                    placeholder="Select your city..."
                    choices
                    reset-on-new-remote-url
                />

I will like to prevent the select component with the remote-url attribute from making an ajax call before the country_code is changed. for now it makes a call as soon as the page is loaded.

J87NL commented 1 year ago

I noticed the same, an option to not call the remote-url as long as the ${form.country_code} is empty could be nice.

thecyrilcril commented 1 year ago

I tried hacking this by triggering a function on @search like so: I tried to mirror and populate the choices via event.srcElement.__vueParentComponent.ctx.choicesInstance.config.choices Unfortunately, the new results did not render

                           if (event.detail.value.length > 2) {
                               const searchKeyword = `?search=${event.detail.value}`
                               const response = await $splade.request(`/country/cities/${country_code}${searchKeyword}`, 'GET', {})
                               const cities = JSON.parse(response.request.response)
                               delete cities['splade']
                               citiesArray = Object.values(cities)

                               event.srcElement.__vueParentComponent.ctx.choicesInstance.config.choices.length = 0
                               let ch = citiesArray.map(function (city) {
                                   return {
                                       value: city,
                                       label: city,
                                       selected: false,
                                       disabled: false,
                                       placeholder: false,
                                       customProperties: {}
                                }
                            })
                            event.srcElement.__vueParentComponent.ctx.choicesInstance.config.choices = ch
                       }
                        console.log(event.srcElement.__vueParentComponent.ctx.choicesInstance.config.choices)

                    }

@pascalbaljet any help or pointers?

jamesj2 commented 1 year ago

@thecyrilcril I'm wondering if you've looked into the Lazy component in Splade? I don't have any experience with it. But it does have a conditional load option.

thecyrilcril commented 1 year ago

@pascalbaljet @J87NL a simpler approach - the city_name is updated with the search term which is in turn appended to the remote-url attribute as a query string

               <x-splade-select name="city_name"
                    @search="form.city_name=$event.detail.value
                    label="Select your city"
                    remote-url="`/country/cities/${form.country_code}?search=${form.city_name}`"
                    placeholder="Select your city..."
                    choices
                    select-first-remote-option
                />

Unfortunately, the experience is terrible as xhr request are fired off on every keystroke. @pascalbaljet is there a way to debounce this?

thecyrilcril commented 1 year ago

@thecyrilcril I'm wondering if you've looked into the Lazy component in Splade? I don't have any experience with it. But it does have a conditional load option.

I have checked it a bit, can't see how it applies to my situation. thanks

jamesj2 commented 1 year ago

@thecyrilcril I played around with the Lazy component and got it to mostly work but I wasn't able to access the form object. Then I tried using the Data component and I got it working. Choices will not load on page load because the url is initially empty.

<x-splade-data default="{remote_url: ''}">
    <x-splade-form>
        <x-splade-select name="country_code"
                         label="Select your country"
                         :options="$countries"
                         placeholder="Select your country..."
                         choices
                         @change="data.remote_url = '/country/cities/' + $event.target.value"
        />
        <x-splade-select name="city_name"
                         label="Select your city"
                         remote-url="`${data.remote_url}`"
                         placeholder="Select your city..."
                         choices
                         reset-on-new-remote-url
        />
    </x-splade-form>
</x-splade-data>
thecyrilcril commented 1 year ago

@thecyrilcril I played around with the Lazy component and got it to mostly work but I wasn't able to access the form object. Then I tried using the Data component and I got it working. Choices will not load on page load because the url is initially empty.

<x-splade-data default="{remote_url: ''}">
    <x-splade-form>
        <x-splade-select name="country_code"
                         label="Select your country"
                         :options="$countries"
                         placeholder="Select your country..."
                         choices
                         @change="data.remote_url = '/country/cities/' + $event.target.value"
        />
        <x-splade-select name="city_name"
                         label="Select your city"
                         remote-url="`${data.remote_url}`"
                         placeholder="Select your city..."
                         choices
                         reset-on-new-remote-url
        />
    </x-splade-form>
</x-splade-data>

My use case has changed from when I asked the question.

I now only want to load cities that match the search term(this happens on the back end) instead of loading all the cities as choices and the browser have trouble loading that much options without freezing(Ex. 19000+ cities in the US)

I will look take a look, thanks

thecyrilcril commented 1 year ago

@J87NL

I think this approach will really work for you. like I mentioned earlier my situation needs a debounce function so it's not firing off Ajax request on every input.

Has anyone figured out how to debounce an event within the x-splade-form component?

jamesj2 commented 1 year ago

@thecyrilcril I was looking at the docs today and see there is already an option for your initial issue. Please try the select-first-remote-option. Also you can control how many results you get back with the choices attribute, check the choices documentation.

<x-splade-select name="region" remote-url="`/api/regions/${form.country}`" reset-on-new-remote-url select-first-remote-option choices={ searchResultLimit: 5}/>
pascalbaljet commented 1 year ago

In the latest 1.4.16 release, you may do this:

<x-splade-select name="region" remote-url="form.country ? `/api/regions/${form.country}` : null">

That'll prevent an ajax call when the country is empty.