Search code examples
htmlhttp-postthymeleafhttp-get

Can I make HTTP POST request from Thymeleaf table in Spring Boot application


I have a Thymeleaf template in a simple Spring Boot application. The template contains a list in a table as follows:

<p>There are <span th:text="${#lists.size(persons)}"></span> people:</p>
<table th:if="${not #lists.isEmpty(persons)}" border="1">
    <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Address</th>
        <th>Telephone</th>
        <th>Email</th>
        <th>Actions</th>
    </tr>
    <tr th:each="person : ${persons}">
        <td th:text="${person.personId}"></td>
        <td th:text="${person.name}"></td>
        <td th:text="${person.address}"></td>
        <td th:text="${person.telephone}"></td>
        <td th:text="${person.email}"></td>
        <td>
            <a href="#" data-th-href="@{/edit(personId=${person.personId})}">Edit</a> |
            <a href="#" data-th-href="@{/delete(personId=${person.personId})}">Delete</a>
        </td>
    </tr>
</table>

I want to enable edit and delete functionality as per the last cell in the table. But at the moment both requests are for HTTP GET. That is fine for edit where a person's details are fetched from the server for editing, but delete should trigger a POST request because of the data changes on the server.

Does anyone know if Thymeleaf allow a POST request per row of a table? Or do I have to write a simple HTML form per row?

The GET form is currently:

<td>
    <a href="#" data-th-href="@{/edit(personId=${person.personId})}">Edit</a>
    <!--a href="#" data-th-href="@{/delete(personId=${person.personId})}">Delete</a></td-->
    <form method="get" th:action="@{/edit(personId=${person.personId})}">
        <button type="submit" name="submit" value="value">Edit</button>
    </form>
</td>

Where I have a link and a form for testing.

The controller method to be called is:

// Gets a Person.
@RequestMapping(value="/edit", method=RequestMethod.GET)
public String getEditPerson(@RequestParam("personId") String personId, Model model) {
    logger.info(PersonController.class.getName() + ".getEditPerson() method called."); 

    Person person = personDAO.get(Integer.parseInt(personId));
    model.addAttribute("person", person);

    // Set view.      
    return "/edit";
}    

The error when the button version of GET is called is:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Jul 24 00:26:16 BST 2016
There was an unexpected error (type=Bad Request, status=400).
Required String parameter 'personId' is not present`

I am using GET to trigger editing because no data is sent to the server here other than the personId. No database action is taken so it should be a GET.


Solution

  • you are using Links and I don't think that is possible, you would need to use a form where you can specify the method POST to be used.

    In the example below im using a <button> instead of a <a> element, but it will work, the only thing you need to do is to style your button with CSS to look like your links

    <form method="POST" th:action="@{/edit(personId=${person.personId})}">
        <button type="submit" name="submit" value="value" class="link-button">This is a link that sends a POST request</button>
    </form> 
    

    now in your code should look like this

    <tr th:each="person : ${persons}">                
        <td th:text="${person.personId}"></td>
        <td th:text="${person.name}"></td>
        <td th:text="${person.address}"></td>
        <td th:text="${person.telephone}"></td>
        <td th:text="${person.email}"></td>
        <td>
            <form method="POST" th:action="@{/edit(personId=${person.personId})}">
                <button type="submit" name="submit" value="value" class="link-button">EDIT</button>
            </form> | 
            <form method="POST" th:action="@{/delete(personId=${person.personId})}">
                <button type="submit" name="submit" value="value" class="link-button">DELETE</button>
            </form>
        </td>
    </tr>
    

    EDIT

    As you just shared you Java code, in the controller you are expecting the personId not as a PathVariable, but as a RequestParam, in that case your form should have that value...

    edit your form and add the person id as follows.

    <form method="POST" th:action="@{/edit}">
        <input type="hidden" name="personid" id="personId" th:value="${person.personId}" />
        <button type="submit" name="submit" value="value" class="link-button">This is a link that sends a POST request</button>
    </form> 
    

    Notice also I changed the action of the form to be just /edit, as its what your controller looks like