Search code examples
htmx

HTMX cascade load AND change


What I have working:

  1. initial get/load for a Company select field
  2. based on 1st selected default Company option, automatically load options for Building select
  3. based on the 1st selected default Building option, automatically load a list of checkboxes

After everything is loaded:

  • selecting a company will reload the buildings
  • selecting a building will reload the rooms

However, selecting a company (which reloads the building), does not reload the rooms based on the default selected building.

I haven't seen any examples that reload cascading fields. I've seen this htmx three dependent selects immediate population of child elements on change, but it didn't address the issue.
Is this possible?

Here's my code:

Company 

<select 
    id="c" name="c" 
    hx-trigger="load" 
    hx-get="./get_companies.php"
></select> 

Building 

<select 
    id="b" name="b" 
    hx-get="./get_bldgs.php" 
    hx-trigger="load from:#c delay:250ms, change from:#c delay:250ms" 
    hx-include="#c"
></select>

Room

<span 
    id="r"
    hx-get="./get_rooms.php"
    hx-trigger="load from:#b delay:1s, change from:#b delay:1s"
    hx-include="#b"
></span>

Thanks


Solution

  • Your Rooms are listening to load and change events. When you select a Company, the Building is reloaded but at that point, neither load nor change event will be fired. See the JavaScript docs about the load:

    The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets, scripts, iframes, and images. This is in contrast to DOMContentLoaded, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.

    That means the event filters on Building and Room (load from:...) are not doing anything, they only load once on initial page load.

    To get the effect you are looking for, listen for htmx:afterSettle event from respective selects. You can restructure your code like so:

    <!--Company-->
    <select ... hx-trigger="load"...></select> 
    
    <!--Company--> 
    <select ...hx-trigger="htmx:afterSettle from:#c...">
    </select>
    
    <!--Room-->
    <span ...hx-trigger="htmx:afterSettle from:#b..."></span>
    

    The only thing to change is replacing load event with htmx:afterSettle on Building and Room. You can leave the rest as is (I only removed them to simply highlight the change).