I have a Spring Boot 3 application that uses Thymeleaf and HTMX. The application has a createLetter.html
Thymeleaf template, which has a form that saves the entered data into a LetterForm
object.
...
<form th:action="@{/letter-from-template}" method="post" th:object="${letterForm}"
name="createLetterFromTemplateForm">
...
<div>
<label for="textBlockDescription">Text block description: </label>
<select th:name="textBlockDescription" id="textBlockDescription"
th:field="*{textBlocks}" multiple size="4"
hx-get="/text-block" hx-trigger="change"
hx-target="#descriptionFragment" hx-swap="innerHTML">
<option th:each="textBlock : ${textBlocks.values()}"
th:value="${textBlock.id}"
th:text="${textBlock.description}"></option>
</select>
</div>
<div>
<p th:fragment="textBlockDescription" id="descriptionFragment" th:text="${content}"></p>
</div>
<button type="submit">Create</button>
</form>
...
The idea is that when the user clicks on one of the options with a description of a text block, he sees a preview of the contents of this text block. Everything works as it should, but there is a problem with the url that is generated by HTMX to get the text block content.
The Thymeleaf template createLetter.html
contains the hx-get="/text-block"
and th:field="*{textBlocks}"
attributes in the select
tag. And the URL looks like this: localhost:8080/text-block?textBlocks=1
. Somehow the field textBlocks
turns into a request parameter in the url.
I found out that the HTML on the page contains a hidden field named _textBlocks
that is not in my code. Also, the select
tag has a name="textBlocks"
attribute, but in my code the value of this attribute is "textBlockDescription"
.
This is what the generated HTML looks like:
<div>
<label for="textBlockDescription">Text block description: </label>
<input type="hidden" name="_textBlocks" value="1">
<select name="textBlocks" id="textBlockDescription" multiple="" size="4"
hx-get="/text-block" hx-trigger="change"
hx-target="#descriptionFragment" hx-swap="innerHTML" class="">
<option value="1">Text block 1 description</option>
<option value="2">Text block 2 description</option>
<option value="3">Text block 3 description</option>
<option value="4">Text block 4 description</option>
</select>
</div>
How to make the url look like this : localhost:8080/text-block?id=1
.
I have a Spring Boot 3 application that uses Thymeleaf and HTMX. The application has a createLetter.html
Thymeleaf template, which has a form that saves the entered data into a LetterForm
object.
...
<form th:action="@{/letter-from-template}" method="post" th:object="${letterForm}"
name="createLetterFromTemplateForm">
...
<div>
<label for="textBlockDescription">Text block description: </label>
<select th:name="textBlockDescription" id="textBlockDescription"
th:field="*{textBlocks}" multiple size="4"
hx-get="/text-block" hx-trigger="change"
hx-target="#descriptionFragment" hx-swap="innerHTML">
<option th:each="textBlock : ${textBlocks.values()}"
th:value="${textBlock.id}"
th:text="${textBlock.description}"></option>
</select>
</div>
<div>
<p th:fragment="textBlockDescription" id="descriptionFragment" th:text="${content}"></p>
</div>
<button type="submit">Create</button>
</form>
...
The idea is that when the user clicks on one of the options with a description of a text block, he sees a preview of the contents of this text block. Everything works as it should, but there is a problem with the url that is generated by HTMX to get the text block content.
The Thymeleaf template createLetter.html
contains the hx-get="/text-block"
and th:field="*{textBlocks}"
attributes in the select
tag. And the URL looks like this: localhost:8080/text-block?textBlocks=1
. Somehow the field textBlocks
turns into a request parameter in the url.
I found out that the HTML on the page contains a hidden field named _textBlocks
that is not in my code. Also, the select
tag has a name="textBlocks"
attribute, but in my code the value of this attribute is "textBlockDescription"
.
This is what the generated HTML looks like:
<div>
<label for="textBlockDescription">Text block description: </label>
<input type="hidden" name="_textBlocks" value="1">
<select name="textBlocks" id="textBlockDescription" multiple="" size="4"
hx-get="/text-block" hx-trigger="change"
hx-target="#descriptionFragment" hx-swap="innerHTML" class="">
<option value="1">Text block 1 description</option>
<option value="2">Text block 2 description</option>
<option value="3">Text block 3 description</option>
<option value="4">Text block 4 description</option>
</select>
</div>
How to make the url look like this : localhost:8080/text-block?id=1
.
1 Answer
Reset to default 0The docs on hx-get
are a little misleading:
By default
hx-get
does not include any parameters. You can use thehx-params
attribute to change this
This isn't quite correct, in fact if hx-get
is triggered by an element with a value, it will include it in the query string. This is explained in the docs on parameters:
By default, an element that causes a request will include its value if it has one. If the element is a form it will include the values of all inputs within it.
Your <select>
is having its value included in the get request because that's the default htmx behaviour. If you want to remove it from the query string, you'll need to do so by excluding it in the hx-params
attribute like this:
<select
... (your existing attributes)
hx-params="not textBlocks">
It's worth noting however that the id being included is probably important for you to determine which text block preview to return from the server.
th:field="*{textBlock.id}"
instead ofth:field="*{textBlocks}"
? You need the selected ID, here. (Again, you really need to look at the generated HTML to see for yourself what is actually happening with your HTMX.) – andrewJames Commented Mar 22 at 14:48th:field
works. And howname
attributes are used when submitting forms. You could research those topics.) – andrewJames Commented Mar 22 at 17:49