htmx three dependent selects immediate population of child elements on change - htmx

Consider this HTML page using the HTML Javascript package
<html>
<head>
<script src="https://unpkg.com/htmx.org#1.8.0" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script>
<title>Test</title>
</head>
<body>
<h1>Prova</h1>
<select name="brand" hx-get="/models" hx-target="#models" hx-trigger="change">
<option value='325i'>325i</option>
<option value='325ix'>325ix</option>
<option value='X5'>X5</option>
</select>
<select name="model" id="models" hx-get="/models2" hx-target="#numbers" hx-trigger="change">
</select>
<select name="number" id="numbers">
</select>
</body>
</html>
Consider that endpoints models and models2 return a bunch of options depending on the value of the select being changed.
The response is something like:
<option value='325i'>325i</option>
<option value='325ix'>325ix</option>
<option value='X5'>X5</option>
I wonder how I can make that whenever I change the select brand, that triggers the HTMX GET Request associated with the model select, which itself will populate the numbers select.
What I see happening, right now, is that the change to the brand dropdown triggers the population of the model dropdown.
I would expect the same to happen for the number dropdown as a consequence of the model dropdown value being changed but that is not happening. Can you elucidate me why that is not happening? And in that case how I can fix that using standard HTMX?

Swapping the new content into the models element does not actually trigger the change event on the models element. You'd need to define an additional trigger event to get the models element to issue its hx-get request when the brand changes and therefore the models options are updated. You could do this purely on the client side in HTMX with a delay so that your models selected value is sent. Or you could have a combination of client custom trigger event and a HX-Response Header sent to the client to trigger that event.
Here is an example of a client event. Added a long 3 second delay to illustrate how the trigger from brand needs to wait until the swap has finished. If you just had the from:brand trigger without delay, it would fire instantaneously (before the models content was populated) so that post would not include the preselected model option. Essentially a race condition. Also went ahead and included the brands element in the models2 request. Maybe you didn't want models2 server side logic have to worry about the brand... but if two different brands had the same model name, then you may not know which set of numbers are supposed to be returned... For the following to work correctly, please add id='brand' to your brand select element.
<select name="model" id="models" hx-get="/models2"
hx-target="#numbers" hx-include="#brand"
hx-trigger="change, change from:#brand delay:3s">
</select>
The other way to do this would be to add a custom event into the model hx-trigger and then trigger that client event from the server in a Response Header. Added a short 5 millisecond delay so that HTMX has time to finish the swap before making the call to models2 .. Again, so that the preselected model is included in the request to models2.
Clientside:
<select name="model" id="models" hx-get="?handler=models2"
hx-target="#numbers" hx-include="#brand"
hx-trigger="change, get-numbers from:body delay:5ms">
</select>
Server Side ASP.NET here (your server may need different syntax for adding Response Header)
Response.Headers.Add("HX-Trigger", "get-numbers");

Related

How to have nested select dropdown that will fetch differently for the main list and the dependent list for htmx?

Was requested by maintainer to repost here
Issue
In https://htmx.org/examples/value-select/
I can tell that the make is directly in the html and when it changes, the hx-get is called to fetch a new list of models.
What if I want to have both the make and the model all rely on ajax?
meaning to say
<select name="makes" id="makes" hx-get="/makes" hx-trigger="load">
<option value="none">original</option>
</select>
<select name="models" id="models">
<option value="none">original</option>
</select>
i like to be able to fetch from /makes on load to get the list of makes option
and then somehow I can also fill up the dependent models as well.
I don't mind doing it as two requests. The reason is that in my situation the makes are also dependent on a 3rd party API
I hope I understand what you want, but something like this should work:
<select name="makes" id="makes" hx-get="/makes" hx-trigger="load">
<option value="none">original</option>
</select>
<select name="models" id="models"
hx-get="/models"
hx-trigger="changed from:#makes"
hx-include="#makes">
<option value="none">original</option>
</select>
So you add a trigger to the second drop down that listens for changed events on the #makes drop down and then fires up a request to the /models URL, including the value of the #makes drop down so you know what models to return.
Does that seem like what you want?

How Can I add currency selector on WHMCS custom page?

I am trying to add a currency selector on one of my custom pages where I have displayed the product details.
I want to allow my visitor to change the default currency from this custom page and view the product pricing accordingly.
I have added this code in my custom.tpl
<input type="hidden" name="token" value="{$LANG.go}">
<select name="currency" onchange="submit()" class="form-control">
<option value="">Change Currency (A$ AUD)</option>
{foreach from=$currencies item=listcurr}
<option value="{$listcurr.id}"{if $listcurr.id == $currency.id} selected{/if}>{$listcurr.prefix} {$listcurr.code}</option>
{/foreach}
</select>
</form> ```
But it is not working, every time I select the currency from the dropdown, it refreshes the page. but nothing changes,
please guide what I am doing wrong.
Thanks in advance
Aqsa,
You can do this. You could update your form to either:
Perform a GET request, and add the currency=$id parameter to the URL ($id being the ID for the currency in tblcurrencies.
Or
When your form submits, handle the form input, and set the currency in the session variable:
use WHMCS\Session;
Session::set('currency', $id);
Again, where $id relates to tblcurrencies.id.
Bare in mind that the currency cannot be changed for existing users, and it is not recommended changing their currency after they have made any transactions to avoid accounting/calculation issues.

How can I changed the selected <select> tag element in scrapy?

I'm trying to crawl a website using Scrapy.
I need to query the list of all existing items of a board-like function on my target site.
The problem is that it only searches within a target year, designated with a HTML tag option.
So I need to find a way to changed to location "selected" attribute within the s.
I think I'm not really doing my job at describing my troubles, so I'll append a simplified HTML code of the site:
<select name="Search_FIS_YEAR" id="Search_FIS_YEAR" title="fiscal_year">
<option value="2014" selected>2014</option>
<option value="2013">2013</option>
<option value="2012">2012</option>
...
<option value="2007">2011</option>
</select>
So the default value of my target website is 2014, but I want to programmatically change its value to 2013, 2012, etc.
The search query is sent through a large that makes a POST request method to the server.
Fortunately I found a way to send the query using FormRequest.from_response, but I wasn't really successful in modifying the above part of the code.
I already knew the answer.
All I did was to just change the value of option within the form data:
yield FormRequest.from_response(
response,
formname=NAME_OF_FORM_WRAPPING_SELECT_HTML_ELEMENT
formdata={
'Search_FIS_YEAR': '2013', # or any other year value
}
callback=self.other_parse_function
)
This did all the tricks for me.

Can a user-sorting system for a collection be done in Shopify?

In Shopify, a collection can have a default sorting order, which is great. But is there a way to change the default sorting order prior to rendering the collection's list of products? What I'm trying to accomplish is to put a "sort by" dropdown menu on the page, allowing the customer to sort the current list by price, by brand, by best selling items, alphabetically, etc. like so many modern shopping carts out there.
Collections are sorted ahead of time rather than sorted dynamically so that pages can load faster.
You can create multiple collections with the same products, but with different sorting. Then you can navigate to relevant collection based on user input.
There is an app for this now:
https://apps.shopify.com/power-tools-sort-selector
*disclaimer - I'm the developer :)
We've recently added the ability to sort your collection dynamically on the storefront (before you could only sort a collection by one order in the backend.
docs:
http://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/add-a-reorder-drop-down-menu-to-a-collection-page
ex code:
https://gist.github.com/carolineschnapp/11352987
If you want to avoid paying for the app - which may or may not duplicate each collection by the number of selections required - use / adapt the code below:
<script>
// jquery is already running on the site, so we use it to check the document is ready
$(document).ready(function() {
// Identify a Select Option from the value in the URL query text
// Where this exists as an Option Value, add the 'selected' attribute to the Option
// This ensures that when the page reloads the current option will be showing
$("#selectSort option[value='{{collection.sort_by}}']").attr('selected', true);
});
</script>
<div>
<!--
The Select Tag watches for a change, then pushes a new window.location using the value
of the Option selected by the user
-->
<select id="selectSort" onchange='window.location="{{ collection.url }}?sort_by=" + this.value'>
<option value="price-ascending">Price (lowest first)</option>
<option value="price-descending">Price (Highest first)</option>
<option value="title-ascending">A-Z</option>
<option value="title-descending">Z-A</option>
<option value="created-descending">Latest Addition</option>
<option value="best-selling">Most Popular</option>
</select>
</div>

Filtering Select - How to add a blank option '-' that allows submission in Dojo

Been trying to fix this for a while now. I have loads of Dojo Filtering Select elements in my form. I need them to have a blank option which should be selected by default. Here is an example (of a normal <select> structure) that I want to emulate:
<select>
<option value="">-</option>
<option value="foo">Bar</option>
</select>
At present when I load up my filtering selects that have the options set as above, there is no element selected. This in turn disables form submission. This is totally unusable for my end users as they would have no idea why the form is not working. The selects are not even required fields.
The problem lies in the way the FilteringSelect stores it's data. It keeps them in a data store that requires an identifier and a label. You can't quite emulate the functionality of a plain select because of this.
You can 'get around' this by putting a fake item in your options with a value of 'XXXX' (or another fake value).
<select>
<option value="XXXX">-</option>
<option value="foo">Bar</option>
</select>
One downside of this kludge is that you need to change your validation functions to look for this fake value (instead of an empty value).
I set up a test on jsbin.com where you can see it in action.