admin管理员组

文章数量:1401930

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.

Share Improve this question edited Mar 22 at 22:13 Roman_Nazarenko asked Mar 22 at 12:43 Roman_NazarenkoRoman_Nazarenko 12 bronze badges 6
  • 2 There is a lot of code in your question which is not relevant to the specific problem you are describing - and that makes it more difficult for the community to recreate/diagnose your problem. You can write a minimal reproducible example - the absolute smallest amount of code needed to demonstrate the specific problem. Also, in this case, you do not show us the rendered HTML - only the Thymeleaf template (and, of course HTMX uses the HTML - it knows nothing about Thymeleaf templates!). – andrewJames Commented Mar 22 at 14:48
  • 1 Having said that (and this is just a suggestion - not a solution), don't you need to be using th:field="*{textBlock.id}" instead of th: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:48
  • @andrewJames Thank you for your advice. I edited my question and added the generated HTML. – Roman_Nazarenko Commented Mar 22 at 17:39
  • There is still no minimal reproducible example, unfortunately. Seriously - start with no code at all and then write the fewest lines of code you can possibly write to demonstrate the specific problem. (Maybe someone else will be able to help you without you doing that.) – andrewJames Commented Mar 22 at 17:47
  • (Also, it looks like maybe you are not familiar with how th:field works. And how name attributes are used when submitting forms. You could research those topics.) – andrewJames Commented Mar 22 at 17:49
 |  Show 1 more comment

1 Answer 1

Reset to default 0

The docs on hx-get are a little misleading:

By default hx-get does not include any parameters. You can use the hx-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.

本文标签: