hx-include including all matching elements in the page, not only from children
Not sure if this is a bug or if I am reading the doc wrong.
Inside a div, .filter-container in the example below, I have multiple inputs that I want to include in a request, so I added hx-include="[input]" to it, but for some reason the input in the outside div is also being included.
<div>
<label for="outside_input">This input is not supposed to be included</label>
<input id="outside_input" name="not_this_one" type="text">
</div>
<div class="filter-container" hx-include="input">
<div class="filter-name">
Include these:
</div>
<div class="filter-range">
<label for="from">From</label>
<input name="from" type="text">
<label for="to">To</label>
<input name="to" type="text">
</div>
<div class="buttons-group">
<button hx-get="/path">Apply</button>
</div>
</div>
When I fill the inputs and click in the Apply button I get path/?not_this_one=99&from=1&to=12, the query parameter not_this_one=99 is the one that should not be there.
From on the doc for hx-include : "Notes: hx-include is inherited and can be placed on a parent element" and the one for inheritance: "Most attributes in htmx are inherited: they apply to the element they are on as well as any children elements. "
So my assumption is that anything outside the element with hx-include should not be selected, is this wrong or is it a bug?
Hey, the query selector passed to hx-include simply resolves to document.querySelectorAll. A standard CSS selector will not take the element defining the hx-include's position in the hierarchy
Take a look at hx-include documentation, where the example code is
<div>
<button hx-post="/register" hx-include="[name='email']">
Register!
</button>
Enter email: <input name="email" type="email"/>
</div>
You can see here, how the included input is not a child of the button, yet is included thanks to the [name='email'] selector.
So what can you do here? You may use the htmx extended selectors, so with your example code, you could do:
-
<button hx-get="/path" hx-include="closest .filter-container">Apply</button>which will include the closest parent element that has thefilter-containerclass, and thus, will include any input that is a child of that container This will not include the outside input, as it's not a child of that container Remember that, as the doc says:Note that if you include a non-input element, all input elements enclosed in that element will be included
-
You may also add the container's class to the selector, to only include inputs that are children of it, not necessarily using the extended selector syntax, such as
hx-include=".filter-container input", which will also ignore any input that is not a child of the container -
Just to expand on available options here, you might as well exclude the input you don't want, using the CSS
:notpseudo-class, such ashx-include="input:not(#outside_input)" -
Also note that, even though I suppose this is just an example here, the doc also mentions
This is a little contrived as you would typically enclose both of these elements in a form and submit the value automatically, but it demonstrates the concept.
In your case, a form would indeed be a much clearer (and standard) option imo, such as
<form class="filter-container" hx-get="/path">
<div class="filter-name">
Include these:
</div>
<div class="filter-range">
<label for="from">From</label>
<input name="from" type="text">
<label for="to">To</label>
<input name="to" type="text">
</div>
<div class="buttons-group">
<button type="submit">Apply</button>
</div>
</form>
Here, you don't even need hx-include since the form handles that by default. You define the hx-get on the form, and use a submit button
Again, I suppose it's just an example you provided here, just thought it was worth mentioning
Hi @Telroshan, thanks for the detailed answer, that makes sense based on the implementation.
Would it make sense to clarify this in the documentation?, the way I read it seems to imply that it uses the concepts described in the "Inheritance" section.
You're right, inheritance is often confusing across attributes & behaviours ! I'll submit a PR sometime soon to improve the doc here (and also provide more code examples for hx-include I think)