Thymeleaf : How to edit a field? - spring

In my class Test I have a list of Versions like this :
Test Class:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "idTest")
private List<Versions> version;
In thymeleaf I code this to display the list of version
<tr th:each ="test : ${testList}">
<td th:each="p : ${test.version}" th:text="${p.getVersions().version}" > </td>
</tr>
This work for me.
Now I would edit it (Version field), my code :
<form class="form-horizontal" th:object="${update}" th:action="#{/update}" method="post">
<div class="col-sm-10">
<th:block th:each="p : ${version}" >
<input type="text" class="form-control" th:field="*{p.getVersions().version}"/>
</th:block>
</div>
</form>
It display only the label Version, and it doesn't show the version input
Have you any idea ?
Thanks.

It seeems you're not iterating the object correctly. Try this:
<tr th:each ="test : ${testList}">
<form class="form-horizontal" th:object="${update}" th:action="#{/update}" method="post">
<div class="col-sm-10">
<th:block th:each="p : ${test.version}" >
<input type="text" class="form-control" th:field="*{p.getVersions().version}"/>
</th:block>
</div>
</form>
</tr>

Related

Spring MVC editable table (Thymeleaf)

I have 2 entities - Invoice and InvoiceProduct. Invoice class has a field List of InvoiceProduct because Invoice has #OneToMany mapping on InvoiceProduct.
I want to send the List of InvoiceProduct to Thymeleaf with with editable fields with a Submit button. When I click on Submit button, the new edited List should be returned to the controller. However, I am able to send the list to the view, but when I send the edited list to controller, it is being passed as 'null'.
update-invoice.html:
<form action="#" th:action="#{/api/invoice/saveInvoice}" th:object="${invoice}" method="POST">
<table class="table table-bordered table-striped">
<thead class="thead-dark">
<tr>
<th>PID</th>
<th>Quantity</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
<tr th:each="temp : ${invoice?.invoiceProducts}" >
<td><input name="invoiceProducts[${tempStat.index}].productId" th:value="${temp.productId}"/></td>
<td><input name="invoiceProducts[${tempStat.index}].quantity" th:value="${temp.quantity}"/></td>
<td><input name="invoiceProducts[${tempStat.index}].price" th:value="${temp.price}"/></td>
</tr>
</tbody>
</table>
<button type="submit" class="btn btn-info col-2">Submit</button>
</form>
InvoiceController:
#PostMapping("/saveInvoice")
public String postInvoice(#ModelAttribute("invoice") Invoice invoice) {
logger.info("invoice products " + invoice.getInvoiceProducts());
return "dummy";
}
What else do I need to add so that my update-invoice.html passes the list to my controller ?
You can try something like below as an example for thymleaf:-
<form method="post" th:action="#{/users/}" th:object="${userInfo}" class="col card p-3 mb-5">
<div class="form-group">
<label for="firstName">First Name</label>
<input id="firstName" placeholder="Enter First Name" required type="text" th:field="*{firstName}"
class="form-control"/>
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input id="lastName" placeholder="Enter Last Name" required type="text" th:field="*{lastName}"
class="form-control"/>
</div>
<div class="form-group">
<label for="role">Role</label>
<select id="role" required th:field="*{role}" class="form-control ">
<option value="" hidden>Select a role</option>
<option th:each="role : ${T(com.springhow.examples.springboot.thymeleaf.domain.entities.Role).values()}"
th:value="${role}"
th:text="${role}">
</option>
</select>
</div>
<input type="submit" class="btn btn-primary" value="Create User">
</form>
and into Controller:-
#RequestMapping(value = "/", method = RequestMethod.POST)
public String createUser(Model model, #ModelAttribute UserInfo userInfo) {
UserInfo user = userService.createUser(userInfo);
return "redirect:/users/";
}

Thymeleaf: How to fix updating #ManyToMany table

I have created a form using thymeleaf for updating books information.
Authors and Book have a #ManyToMany relationship. The problem is that when I save my changes, the #ManytoMany table (Book_Authors) row is deleted.
I am not trying to change the values of authors for the edited book, I simply want to
preserve the old ones.
I have tried saving each author ID in a 'input type = "hidden" ' since
this worked for saving values for #OneToMany relationship like
'PUBLISHER'
This works (Publisher old value is saved in database):
<div class="form-group">
<label class="col-lg-3 control-label">Publisher:</label>
<div class="col-md-8">
<input type="hidden" th:field="*{publisher.id}" />
<input class="form-control" type="text" value="" th:field="
{publisher.name}">
</div>
</div>
This doesn't work:
<div th:each = "author : ${authors}">
<input type="hidden" th:field="*{author.id}" />
</div>
<tr th:each="vehicle, itemStat : ${form.vehicles}">
<td>
<input hidden th:name="|vehicles[${itemStat.index}].id|" th:value="${vehicle.getId()}"/>
</td>
<td>
<input th:name="|vehicles[${itemStat.index}].brand|" th:value="${vehicle.getBrand()}"/>
</td>
<td>
<input th:name="|vehicles[${itemStat.index}].price|" th:value="${vehicle.getPrice()}"/>
</td>
</tr>
further reading : -
https://www.baeldung.com/thymeleaf-list
http://forum.thymeleaf.org/I-have-problem-in-binding-the-list-of-objects-contained-inside-a-object-on-the-form-using-thymeleaf-td3525038.html
and also u have to change cascadeType.ALL
if use #OneToMany use orphanRemoval=true

How to perform arithmetic operations of two different data types in thymeleaf?

I have a piece of HTML where I need to multiply (or perform arithmetic operations) two values using thymeleaf.
Let's say my price is double and quantity is an integer.
Here's my sample code:
<fieldset class="form-inline" disabled >
<label for= "prodAmount">AMOUNT: </label>
<input type="number" class="form-control" th:text="${#aggregates.sum(product.![price * qty])}">
</fieldset>
Here's the error I'm getting:
Exception evaluating SpringEL expression: "#aggregates.sum(product.![price * qty])"
Also , I would also like to ask how to perform this when there's two or more values.
Here's my html form
<div class="container">
<div class="row">
<div class="col-lg-4 col-sm-12 col-xs-12">
<form th:action="#{/product/product-list}" method="post" th:object="${productEntity}">
<input type="hidden" th:field="*{pid}" th:value="${pid}" >
<fieldset class="form-group">
<label for="product_name">Product Name</label>
<input type="text" class="form-control" th:field="*{pName}" th:value="${pName}">
</fieldset>
<fieldset class="form-group">
<label for="price">Price</label>
<input type="number" class="form-control" th:field="*{price}" th:value="${price}" placeholder="0">
</fieldset>
<fieldset class="form-group">
<label for="pQty">Quantity</label>
<input type="number" class="form-control" th:field="*{qty}" th:value="${qty}" placeholder = "0">
</fieldset>
<fieldset class="form-group">
<label for="status">Status</label>
<select class="form-control" id="select_status" th:field="*{status}" th:value="${status}">
<option value="0">AVAILABLE</option>
<option value ="1">NOT AVAILABLE</option>
</select>
</fieldset>
<fieldset class="form-group">
<label for="image">Image</label>
<input id="input-b2" name="input-b2" type="file" class="file"
data-show-preview="false" th:field="*{image}" th:value="${image}">
</fieldset>
</form>
</div>
<div class="col-lg-8 col-sm-12 col-xs-12">
<table class="table table-inverse table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
<th>Status</th>
<th>Image</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr th:each="product : ${productTable} ">
<td th:text="${product.pid}"></td>
<td th:text="${product.pName}"></td>
<td th:text="${product.price}"></td>
<td th:text="${product.qty}"></td>
<td th:text="${product.status == '0'} ? 'Available' : 'Not Available'"></td>
<td th:text="${product.image}"></td>
<td>
<a th:href="#{/productlist/{id}(id = ${product.pid})}" class="btn btn-primary">Update</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row float-right">
<div class="col-xd-12">
<div>
<fieldset class="form-inline" disabled >
<label for= "prodAmount">AMOUNT: </label>
<input type="number" class="form-control" th:text="${#aggregates.sum(product.{price * qty})}">
</fieldset>
<button type="button" class="btn btn-primary">Checkout</button>
</div>
</div>
</div>
</div>
Product Controller:
#RequestMapping(value="/product-list")
public ModelAndView shopView() {
ModelAndView mav = new ModelAndView();
mav.addObject("productTable", pRepo.findAll());
mav.addObject("productEntity",new ProductEntity());
mav.setViewName("/productlist");
return mav;
}
#RequestMapping(value = "/{id}",method = RequestMethod.GET)
public ModelAndView getProduct(#ModelAttribute ProductEntity productEntity, #PathVariable int id) {
ModelAndView mav = new ModelAndView();
mav.addObject("productTable",pRepo.findAll());
mav.addObject("productEntity", pRepo.findOne(id));
mav.setViewName("/productlist");
return mav;
}

How do I assign an object to a member class in JSP

I am building a tour application. I have bookings which point to a tour modality but I haven't been able to assign the book modality when adding a new booking using JSLT.
Here's my JSP code:
<c:forEach items="${modalities}" var="modality">
<form:form method="POST" action="/book_tour" modelAttribute="booking">
<p>${modality.name}</p>
<jsp:setProperty name="booking" property="tourModality" value="${modality}"></jsp:setProperty>
<input name="modality" type="hidden" value="${modality}">
<div class="form-group">
<form:label path="calendarDate">Escoja una fecha</form:label>
<div class='input-group date' id='datetimepicker'>
<form:input path="calendarDate" type='text' class="form-control"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
<div class="input-group">
<form:label path="calendarDate">Hora: </form:label>
<form:select path="calendarDate">
<c:forEach items="${modality.tourHours}" var="tourHour">
<option>${tourHour.timeSlot}</option>
</c:forEach>
</form:select>
</div>
</div>
<input type="submit" class="btn btn-success" value="Reservar"/>
</form:form>

empty object in controller from thymeleaf form

I have a table showing testResults using thymeleaf template -
<tr th:each="testResult,iterationStatus : ${testResults}">
<td th:text="${iterationStatus.count}">1</td>
<td th:text="${testResult.name}">DOMAIN</td>
<td th:text="${testResult.length}">PROCESS</td>
<td>
<form ACTION="#" th:action="#{/deleteName}" th:object="${testResult}" method="POST">
<input type="hidden" th:field="*{name}"/>
<input type="hidden" th:field="*{length}"/>
<button type="submit">submit</button>
</form>
</td>
</tr>
name and length are showing fine in the html, but when i submit the form, controller gets name and length as empty values.
What i am doing wrong in assigning the values....
below is controller method that gets invoked -
#RequestMapping(method= RequestMethod.POST, value = "/deleteName")
public String deleteName(#Valid #ModelAttribute("testResult") TestResult testResult, BindingResult bindingResult, Model model, HttpServletRequest request) {
System.out.println(testResult.toString());
return "/";
}
output once i submit the form -
TestResult [name=, length=, xyz=null]
I couldn't get th:field to work inside a th:object, like you're doing here. However, if I stop using th:field, and use th:value instead, the form submits successfully.
<tr th:each="testResult : ${testResults}">
<td th:text="${testResult.name}">DOMAIN</td>
<td th:text="${testResult.length}">PROCESS</td>
<td>
<form ACTION="#" th:action="#{/deleteName}" method="POST">
<input type="hidden" name="name" th:value="${testResult.name}"/>
<input type="hidden" name="length" th:value="${testResult.length}"/>
<button type="submit">submit</button>
</form>
</td>
</tr>

Resources