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.
Thymeleaf is way better in my opinion because it have good underlying priciples and exploits natural behaviour of browsers. Jsp makes html hard to read, it becomes weird mixture of html and java code which makes a lot of problems in comunication between designer - developer.
Thymeleaf is server rendered, it's not front end.
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
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?
HTML doesn't support POST request with links and you have to use forms (as Rayweb_on explained). But Thymeleaf allows you to define custom tags which helps a lot :
<a th:href="@{/edit(personId=${person.personId})}" custom:linkMethod="post">Edit</a>
... which would generate following HTML (assuming jQuery is available) :
<a href="#" onclick="$('<form action="/edit/personId=123456" method="post"></form>').appendTo('body').submit(); return false;">Edit</a>
Custom tag definition (without error checking to keep it simple) :
/**
* Custom attribute processor that allows to specify which method (get or post) is used on a standard link.
*/
public class LinkMethodAttrProcessor extends AbstractAttributeTagProcessor {
private static final String ATTR_NAME = "linkMethod";
private static final int PRECEDENCE = 10000;
public LinkMethodAttrProcessor(final String dialectPrefix) {
super(
TemplateMode.HTML, // This processor will apply only to HTML mode
dialectPrefix, // Prefix to be applied to name for matching
null, // No tag name: match any tag name
false, // No prefix to be applied to tag name
ATTR_NAME, // Name of the attribute that will be matched
true, // Apply dialect prefix to attribute name
PRECEDENCE, // Precedence (inside dialect's own precedence)
true); // Remove the matched attribute afterwards
}
@Override
protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag,
final AttributeName attributeName, final String attributeValue,
final IElementTagStructureHandler structureHandler) {
// get the method name (tag parameter)
final IEngineConfiguration configuration = context.getConfiguration();
final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);
final IStandardExpression expression = parser.parseExpression(context, attributeValue);
final String method = (String) expression.execute(context);
// add custom javascript to change link method
final String link = tag.getAttribute("href").getValue();
final String action = "$('<form action="" + link + "" method="" + method + ""></form>').appendTo('body').submit(); return false;";
structureHandler.setAttribute("onclick", action);
structureHandler.setAttribute("href", "#");
}
}
See the Thymelead documentation for example of how this custom attribute needs to be registered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With