sending multiple row data (table) from HTML to Spring controller using thymeleaf - java

I am working on application using html, thymeleaf, Spring MVC, I wanted to send table data to spring controller but in when I clicked on save button of the application, getting an error on console:
java.lang.IllegalStateException: Neither BindingResult nor plain
target object for bean name 'salesProduct[0]' available as request
attribute
at org.springframework.web.servlet.support.BindStatus.(BindStatus.java:144)
at org.thymeleaf.spring4.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:396)
Browser Error:
HTTP Status 500 - Request processing failed; nested exception is
org.thymeleaf.exceptions.TemplateProcessingException: Error during
execution of processor
'org.thymeleaf.spring4.processor.attr.SpringInputGeneralFieldAttrProcessor'
(sales:290)
I have added three attributes to controller like salesBean, paymentBean and salesProductFormBean, you can see in below spring controller code that is the reason in html I have not added th:object="${...}" in the form tag.
HTML
Sales.html
<form th:action="#{/salesForm}" method="post" class="mainData"
id="form">
<div class="buttonBar" id="mainbutton">
<div>
<button class="btn" id="save" type="submit">
<img th:src="#{/resources/images/save.svg}" /> Save
</button>
<button class="btn" id="reset" onclick="clearForm()" type="reset">
<img th:src="#{/resources/images/reset.svg}" /> Reset
</button>
<button type="button" class="btn" id="clientNew">
<img th:src="#{/resources/images/notebook.svg}" /> Client Creation
</button>
</div>
</div>
<div class="container">
<div class="mp-pusher" id="mp-pusher">
<nav id="mp-menu" class="mp-menu"></nav>
<div class="scroller-inner"></div>
<div class="containerMain">
<div class="mainArea">
<div class="inputArea">
<div class="ccode">
<lable class="lable">Client code</lable>
<input type="text" class="inputfield" id="ccode"
th:field="*{salesBean.client.clientId}" />
<button type="button" class="inputbutton" id="clientData"></button>
</div>
<div>
<ul class="tabs" data-persist="true">
<li>Basic data</li>
<li>Payment</li>
</ul>
<div class="tabcontents">
<div id="tab1">
<div class="invNo">
<lable class="lable">Invoice number</lable>
<input type="text" id="invNo" th:field="*{salesBean.salesId}"
name="salesId" class="inputfield disabled"
readonly="readonly" />
</div>
<div class="invdate calendar">
<lable class="lable">Invoice date</lable>
<input type="date" class="inputfield" id="invdate"
th:field="*{salesBean.invoiceDate}" /> <span
class="calendar"><img
th:src="#{/resources/images/calendar.svg}" /></span>
</div>
<div class="txtChallan">
<lable class="lable">Challan number</lable>
<input type="text" class="inputfield" id="txtChallan"
th:field="*{salesBean.challanNumber}" />
</div>
<div class="txtChallDt calendar">
<lable class="lable">Date</lable>
<input type="date" class="inputfield" id="txtChallDt"
th:field="*{salesBean.challanDate}" /> <span
class="calendar"><img
th:src="#{/resources/images/calendar.svg}" /></span>
</div>
<div class="txtPO">
<lable class="lable">P. O. ID</lable>
<input type="text" class="inputfield" id="txtPO"
th:field="*{salesBean.purchaseOrderId}" />
</div>
<div class="txtPoDt calendar">
<lable class="lable">Date</lable>
<input type="date" class="inputfield" id="txtPoDt"
th:field="*{salesBean.purchaseOrderDate}" /> <span
class="calendar"><img
th:src="#{/resources/images/calendar.svg}" /></span>
</div>
</div>
<div id="tab2">
<div class="txtCash">
<lable class="lable">Cash</lable>
<input type="number" class="inputfield" id="txtCash"
th:field="*{paymentBean.cash}" />
</div>
</div>
</div>
<!-- tabcontents -->
</div>
<!-- blank -->
<!-- for autocomplete -->
<div class="ui-widget" id="autocomplete_desc">
<div class="tableArea">
<div class="tablePanel">
<div class="tableButtonBar">Material entry</div>
<section class="tableHolder">
<table id="invoicetable" class="transactionTable table"
cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>Serial</th>
<th>Description</th>
<th>Nos.</th>
<th>Quantity</th>
<th>Rate</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr
th:each="salesProduct, stat: *{salesProductFormBean.salesProducts}">
<td th:text="${stat.count}">1</td>
<td><input type="text"
**Line no: 290** th:field="*{salesProduct[__${stat.index}__].numbers}" /></td>
<td><select type="select" class="selectfield"
id="product"
th:field="*{salesProduct[__${stat.index}__].product.productId}">
<option value="Select"></option>
<option th:each="prdList : ${productList}"
th:value="${prdList.productId}"
th:text="${prdList.productName}"></option>
</select></td>
<td><input type="number"
th:field="*{salesProduct[__${stat.index}__].quantity}" /></td>
<td><input type="number"
th:field="*{salesProduct[__${stat.index}__].rate}" /></td>
<td><input type="number"
th:field="*{salesProduct[__${stat.index}__].amount}" /></td>
</tr>
</tbody>
</table>
</section>
</div>
<!-- tablePanel -->
</div>
<!-- tableArea -->
</div>
</div>
<!-- inputArea -->
</div>
<!-- mainArea -->
</div>
<!-- containerMain -->
</div>
<!-- /container -->
</div>
</form>
Controller
#Autowired
private List<SalesProduct> salesProducts= new ArrayList<SalesProduct>();
#ModelAttribute("salesProducts")
public List<SalesProduct> salesProducts() {
return salesProducts;
}
#RequestMapping(value= "/sales", method = RequestMethod.GET)
public String salesInvoicePage(final ModelMap model) {
String userName = LoginController.getPrincipal();
model.addAttribute("user", userName);
model.addAttribute("salesBean", new Sales());
model.addAttribute("paymentBean", new Payment());
SalesProductForm salesProductForm = new SalesProductForm();
SalesProduct salesProduct= new SalesProduct();
salesProducts.add(salesProduct);
salesProductForm.setSalesProducts(salesProducts);
model.addAttribute("salesProductFormBean", salesProductForm);
//model.addAttribute("salesProducts", salesProducts);
List<Product> productList= productService.list();
model.addAttribute("productList", productList);
return "sales";
}
Model
public class SalesProduct implements java.io.Serializable {
private Integer salesProductId;
private Product product;
private UserDetail userDetailByModifiedBy;
private UserDetail userDetailByCreatedBy;
private Date createdDate;
private Date modifiedDate;
private String numbers;
private Float quantity;
private Float rate;
private Float amount;
private Set<Sales> saleses = new HashSet<Sales>(0);
//Setter and Getters
}
public class SalesProductForm {
private List<SalesProduct> salesProducts;
public List<SalesProduct> getSalesProducts() {
return salesProducts;
}
public void setSalesProducts(List<SalesProduct> salesProducts) {
this.salesProducts = salesProducts;
}
}
I got stuck in this issue but dont know what am I missing. Does anyone knows what am I doing wrong?

Related

How to set a object's field using another objects field in thymeleaf

I'm trying to set boxes' elements copied from medicineBox's values like below. Can anyone help me in this. I need to post medicineOrder model to the controller
<tr th:each="medicineBox : ${medicine.medicineBoxes}">
<td class="text-center">
<input type="text" th:field="*{boxes[__${medicineBoxStat.index}__].boxNumber}" th:value="${medicineBox.box.number}" />
</td>
<td class="text-center" th:text="${medicineBox.medicineCount}"></td>
<td><input type="number" th:field="*{boxes[__${medicineBoxStat.index}__].medicineCount}" class="form-control" /></td>
</tr>
I'm using two object here -
medicine and medicineOrder
------------------> Controller method to get the page
#GetMapping("/{medicineId}")
public String loadMedicineDetailPage(#PathVariable("medicineId") long medicineId, Model model) {
model.addAttribute("medicine", service.getMedicineById(medicineId));
model.addAttribute("medicineOrder", new MedicineOrder());
return WebPages.MEDICINE_DETAIL.toString();
}
------------------> thymeleaf html page
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1"/>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Spring Boot Application</title>
</head>
<body>
<div class="container">
<br/>
<a class="btn btn-primary" th:href="#{/mvc/medicine/list}">Back</a>
<br/>
<br/>
<h3 class="text-center alert alert-success">Medicine Details</h3>
<form class="row g-3" action="#" th:action="#{/mvc/medicine/sell}" method="post" th:object="${medicineOrder}">
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="name" class="form-label">Name</label>
<input type="text" style="background-color:#95edea" disabled class="form-control" id="name" th:field="${medicine.name}"/>
</div>
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="company" class="form-label">Company</label>
<input type="text" disabled class="form-control" id="company" th:field="${medicine.companyStringName}"/>
</div>
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="price" class="form-label">Price</label>
<input type="text" disabled class="form-control" id="price" th:field="${medicine.price}"/>
</div>
<!--<div class="col-md-6 col-xs-12 col-sm-12">
<label for="count" class="form-label">Count</label>
<input type="text" class="form-control" id="count" th:field="${medicine.count}"/>
</div>-->
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="volume" class="form-label">ML</label>
<input type="text" disabled class="form-control" id="volume" th:field="${medicine.volume}"/>
</div>
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="purchaseDate" class="form-label">Date Purchased</label>
<input type="text" disabled class="form-control" id="purchaseDate" th:field="${medicine.purchaseDate}"/>
</div>
<!--<div class="col-md-6 col-xs-12 col-sm-12">
<label for="boxNo" class="form-label">Box Number</label>
<input type="text" class="form-control" id="boxNo" th:field="${medicine.boxNumber}"/>
</div>-->
**<input type="hidden" th:field="*{medicineId}" th:value="${medicine.medicineId}"/>**
<table class="table table-bordered">
<tr class="table-primary">
<td>Box Number</td>
<td>Medicine Count</td>
<td>Sell Count</td>
</tr>
<tr th:each="medicineBox : ${medicine.medicineBoxes}">
<td class="text-center">
**<input type="text" th:field="*{boxes[__${medicineBoxStat.index}__].boxNumber}" th:value="${medicineBox.box.number}"** />
</td>
<td class="text-center" th:text="${medicineBox.medicineCount}"></td>
<td><input type="number" th:field="*{boxes[__${medicineBoxStat.index}__].medicineCount}" class="form-control" /></td>
</tr>
</table>
<button class="btn btn-primary" type="submit">Sell</button>
</form>
</div>
</body>
</html>
---------------> Controller method to handle the post request
#PostMapping("/sell")
public String sellMedicine(#ModelAttribute MedicineOrder medicineOrder, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
// error handling
}
service.sellMedicine(medicineOrder);
return "redirect:/mvc/medicine/list";
}
----------------> Class MedicineOrder
package com.example.demo.dto;
import com.example.demo.model.Box;
import java.util.ArrayList;
import java.util.List;
public class MedicineOrder {
private long medicineId;
private List<OrderedBox> boxes = new ArrayList<>();
public long getMedicineId() {
return medicineId;
}
public void setMedicineId(long medicineId) {
this.medicineId = medicineId;
}
public List<OrderedBox> getBoxes() {
return boxes;
}
public void setBoxes(List<OrderedBox> boxes) {
this.boxes = boxes;
}
#Override
public String toString() {
return "MedicineOrder{" +
"medicineId=" + medicineId +
", boxes=" + boxes +
'}';
}
}
package com.example.demo.dto;
public class OrderedBox {
private String boxNumber;
private int medicineCount;
public String getBoxNumber() {
return boxNumber;
}
public void setBoxNumber(String boxNumber) {
this.boxNumber = boxNumber;
}
public int getMedicineCount() {
return medicineCount;
}
public void setMedicineCount(int medicineCount) {
this.medicineCount = medicineCount;
}
#Override
public String toString() {
return "OrderedBox{" +
"boxNumber='" + boxNumber + '\'' +
", medicineCount=" + medicineCount +
'}';
}
}
Not able to get the MedicineOrder.medicineId and medicineBorder.boxes[*].boxNumber from template to model object.
After lot of searching I didn't find any answer which is solving the issue only using thymeleaf.
To solve this issue I had to add two hidden input field for medicineId and boxNumber on medicineOrder object and populate those input field using javascript as below. Anyway if anyone find the solution by only using thymeleaf, please let me know.
Populated those fields using javascript
<script>
function function__02__number__assignment(_element){
var __element = _element.children[0];
var __tElement1 = __element.children[0];
var __tElement2 = __element.children[1];
// Copy value from 2 to 1
__tElement1.value = __tElement2.value;
}
function function__01__box_traverse(){
var rootElement = document.getElementsByClassName('box-stock-details');
for(var __i=0 ; __i < rootElement.length ; __i++) {
function__02__number__assignment(rootElement[__i]);
}
function_01_01_medicineId();
return true;
}
function function_01_01_medicineId(){
var _00_1_id_src = document.getElementById('00-1-id-src');
var _00_1_id_dest = document.getElementById('00-1-id-dest');
_00_1_id_dest.value = _00_1_id_src.value;
}
</script>
updated template file
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1"/>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Spring Boot Application</title>
</head>
<body>
<div class="container">
<br/>
<a class="btn btn-primary" th:href="#{/mvc/medicine/list}">Back</a>
<br/>
<br/>
<h3 class="text-center alert alert-success">Medicine Details</h3>
<form class="row g-3" action="#" th:action="#{/mvc/medicine/sell}" method="post" th:object="${medicineOrder}">
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="name" class="form-label">Name</label>
<input type="text" style="background-color:#95edea" disabled class="form-control" id="name" th:field="${medicine.name}"/>
</div>
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="company" class="form-label">Company</label>
<input type="text" disabled class="form-control" id="company" th:field="${medicine.companyStringName}"/>
</div>
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="price" class="form-label">Price</label>
<input type="text" disabled class="form-control" id="price" th:field="${medicine.price}"/>
</div>
<!--<div class="col-md-6 col-xs-12 col-sm-12">
<label for="count" class="form-label">Count</label>
<input type="text" class="form-control" id="count" th:field="${medicine.count}"/>
</div>-->
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="volume" class="form-label">ML</label>
<input type="text" disabled class="form-control" id="volume" th:field="${medicine.volume}"/>
</div>
<div class="col-md-6 col-xs-12 col-sm-12">
<label for="purchaseDate" class="form-label">Date Purchased</label>
<input type="text" disabled class="form-control" id="purchaseDate" th:field="${medicine.purchaseDate}"/>
</div>
<!--<div class="col-md-6 col-xs-12 col-sm-12">
<label for="boxNo" class="form-label">Box Number</label>
<input type="text" class="form-control" id="boxNo" th:field="${medicine.boxNumber}"/>
</div>-->
<!-- Hidden input to get the value of medicineId from Medicine object -->
<input id="00-1-id-src" type="hidden" th:value="${medicine.medicineId}"/>
<!-- Hidden input to set the medicineId on MedicineOrder object -->
<input id="00-1-id-dest" type="hidden" th:field="*{medicineId}" />
<table class="table table-bordered">
<tr class="table-primary">
<td>Box Number</td>
<td>Medicine Count</td>
<td>Sell Count</td>
</tr>
<tr class="box-stock-details" th:each="medicineBox : ${medicine.medicineBoxes}">
<td class="text-center">
<input hidden th:field="*{boxes[__${medicineBoxStat.index}__].boxNumber}" />
<input disabled class="form-control" type="text" th:value="${medicineBox.box.number}" />
</td>
<td class="text-center" th:text="${medicineBox.medicineCount}"></td>
<td><input type="number" th:field="*{boxes[__${medicineBoxStat.index}__].medicineCount}" class="form-control" /></td>
</tr>
</table>
<button class="btn btn-primary" type="submit" onclick="return function__01__box_traverse()">Sell</button>
</form>
</div>
</body>
<script>
function function__02__number__assignment(_element){
var __element = _element.children[0];
var __tElement1 = __element.children[0];
var __tElement2 = __element.children[1];
// Copy value from 2 to 1
__tElement1.value = __tElement2.value;
}
function function__01__box_traverse(){
var rootElement = document.getElementsByClassName('box-stock-details');
for(var __i=0 ; __i < rootElement.length ; __i++) {
function__02__number__assignment(rootElement[__i]);
}
function_01_01_medicineId();
return true;
}
function function_01_01_medicineId(){
var _00_1_id_src = document.getElementById('00-1-id-src');
var _00_1_id_dest = document.getElementById('00-1-id-dest');
_00_1_id_dest.value = _00_1_id_src.value;
}
</script>
</html>

Add object to data table of the page before saving. Spring and Thymeleaf

I'm leaving the JSF environment and I have some doubts when using Spring mvc with Thymeleaf. As in the example below, I have the account object related to a tariff list, what I am trying to accomplish is to add the tariffs of the account being registered in the tariff list that is in my object account, so, when saving the object of the account, fees are recorded through the waterfall. What is the best way to implement this simple funcinality with spring and thymeleaf.
Account Class
public class Account {
private Integer accountNumber;
private BigDecimal balance;
#ManyToOne(targetEntity=Rate.class, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
#JoinColumn(name="RateCode", foreignKey= #ForeignKey(name = "fk_account_rate"))
private List<Rate> rates;
// get and sets
}
Rate
public class Rate {
private Long rateCode;
private String rateName;
private BigDecimal value;
// get and sets
}
Controller Account
#Controller
#RequestMapping("/account")
public class AccountController {
#Autowired AccountRepository accountRepository;
#GetMapping
public ModelAndView new(Account account) {
ModelAndView model = new ModelAndView("page/account/cadAccount");
model.addObject("rate", new Rate());
model.addObject(account);
return model;
}
}
Page Account
<form th:object="${account}" method="POST" th:action="#{/account/save}">
<gff:message/>
<div class="box-body">
<input type="hidden" th:field="*{accountCode}"/>
<div class="row">
<div class="col-md-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active">Account</li>
<li>Rates</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_conta">
<div class="row">
<div class="col-md-4">
<div class="form-group" gff:classforerror="name">
<label>Account name</label>
<input type="text" th:field="*{name}" class="form-control input-sm">
</div>
</div>
<div class="form-group col-md-4" gff:classforerror="balance">
<label>Balance</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-dollar"></i></span>
<input type="text" th:field="*{balance}" data-thousands="." data-decimal="," data-prefix="R$ " class="form-control currency input-sm">
</div>
</div>
</div>
</div>
<div class="tab-pane" id="tab_tarifas">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<label>Rate Name</label>
<input id="nomeTarifa" type="text" th:field="${rate.name}" class="form-control input-sm">
</div>
</div>
<div class="form-group col-md-3">
<label>Value</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-dollar"></i></span>
<input id="valorTarifaID" type="text" th:field="${rate.value}" data-thousands="." data-decimal="," data-prefix="R$ " class="form-control currency input-sm">
</div>
</div>
<div class="form-group col-md-2">
<a class="btn btn-info pull-left" th:href="#{/account/add}">
<i class="fa fa-plus"></i>
Add
</a>
</div>
<div class="col-md-12">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td data-title="Name"></td>
<td data-title="Value"></td>
</tr>
</tbody>
<tfoot>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="box-footer">
<button id="salveButtonID" type="submit" class="btn btn-primary ajax">Salve</button>
<a class="btn btn-default ajax" th:href="#{/}">Cancel</a>
</div>
</form>

Spring boot + Thymeleaf - Object with id null when editing

When you select an Expense object from the data table for editing, the edit method in the controller sends the Expense object to the edit screen that is the same to insert a new record. When the object is sent to the save method, it has nullo code attribute where an insert occurs instead of an update. I do not understand why.
Controller
#Controller
#RequestMapping("/despesas")
public class DespesaController {
#Autowired private DespesaService despesaService;
#Autowired private DespesaRepository despesaRepository;
#GetMapping("/add")
public ModelAndView novo(Despesa despesa) {
ModelAndView model = new ModelAndView("page/cadastro/despesa/cadDespesa");
model.addObject("tiposDespesa", TipoDespesa.values());
model.addObject("formasPagamento", FormaPagamento.values());
model.addObject(despesa);
return model;
}
#PostMapping("/save")
public ModelAndView salvar(Despesa despesa, BindingResult result, RedirectAttributes attributes) {
if (result.hasErrors()) {
return novo(despesa);
}
despesa.setDataDespesa(new Date());
despesaService.salvarDespesa(despesa);
attributes.addFlashAttribute("mensagem", "Despesa Salva com Sucesso!");
return new ModelAndView("redirect:/cadastroDespesa");
}
#GetMapping("/listDespesa")
public ModelAndView listagemDeDespesas() {
ModelAndView model = new ModelAndView("page/cadastro/despesa/listDespesa");
model.addObject("despesas", despesaRepository.findAll());
return model;
}
#GetMapping("/edit{id}")
public ModelAndView editar(#PathVariable("id") Long codigo) {
return novo(despesaRepository.findOne(codigo));
}
}
FormEdit
<form th:object="${despesa}" method="POST" th:action="#{/despesas/save}">
<div class="box-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Data</label>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" th:field="*{dataDespesa}" class="form-control" disabled="disabled">
</div>
</div>
<div class="form-group">
<label>Valor</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-dollar"></i></span>
<input type="text" th:field="*{valor}" class="form-control">
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Tipo Despesa</label>
<select class="form-control select2" th:field="*{tipoDespesa}" style="width: 100%;">
<option th:each="tipo : ${tiposDespesa}" th:value="${tipo}" th:text="${tipo}"></option>
</select>
</div>
<div class="form-group">
<label>Forma Pagamento</label>
<select class="form-control select2" th:field="*{formaPagamento}" style="width: 100%;">
<option th:each="forma : ${formasPagamento}" th:value="${forma}" th:text="${forma}"></option>
</select>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label>Observação</label>
<input type="text" th:field="*{observacao}" class="form-control">
</div>
</div>
</div>
</div>
<div class="box-footer">
<button type="submit" class="btn btn-primary">Salvar</button>
<a class="btn btn-default" th:href="#{/}">Cancelar</a>
</div>
</form>
Data Table Where I select the object for editing
<table id="example2" class="table table-bordered table-hover">
<thead>
<tr>
<th>Data</th>
<th>Valor</th>
<th>Tipo Despesa</th>
<th>Forma Pagamento</th>
</tr>
</thead>
<tbody>
<tr th:each="obj : ${despesas}">
<td data-title="Data" th:text="${#calendars.format(obj.dataDespesa, 'dd/MM/yyyy HH:mm:ss')}"></td>
<td data-title="Valor" th:text="${#numbers.formatCurrency(obj.valor)}"></td>
<td data-title="Tipo Despesa" th:text="${obj.tipoDespesa}"></td>
<td data-title="Forma Pagamento" th:text="${obj.formaPagamento}"></td>
<td><a th:href="#{/despesas/edit{id} (id=${obj.codigoDespesa})}"><i class="glyphicon glyphicon-pencil"></i></a></td>
</tr>
</tbody>
</table>
As sr.praneeth said you need to add the fields you want to populate into the form, usually the ID are not visible but you need to send them.
<form th:object="${despesa}" method="POST" th:action="#{/despesas/save}">
<div class="box-body">
<input type="hidden" th:field="*{id}"/>
...
</form>
Then in your Controller you will be able to retrieve the id value, null if its a creation, or informed if its an update

Get id value from list jsp

I have view on my jsp like this:
<form:form name = "command"
method = "post"
action = "withdrawRequest"
class = "form-horizontal group-border-dashed"
style = "border-radius: 0px;">
<table class = "table table-bordered"
id = "datatable-icons" > <!-- start table table-bordered -->
<thead>
<tr>
<th>ID</th>
<th>NO</th>
<th>AMOUNT (RP)</th>
<th>DOCTOR BALANCE (RP)</th>
<th>DOCTOR ID</th>
<th>DOCTOR NAME</th>
<th>TRANSFER ADMIN NAME</th>
<th>TRANSFER DATE</th>
<th>TRANSFER REFERENCE</th>
<th>TRANSFERRED</th>
</tr>
</thead>
<tbody>
<c:forEach var = "withdrawal"
items = "${listWithdrawals}"
varStatus = "loopStatus">
<tr class="odd gradeX">
<td>${withdrawal.id}</td>
<td>${loopStatus.index + 1}</td>
<td class="text-right"><fmt:formatNumber type="number" maxFractionDigits="2" value="${withdrawal.amount}" /></td>
<td class="text-right"><fmt:formatNumber type="number" maxFractionDigits="2" value="${withdrawal.doctor_balance}" /></td>
<td>${withdrawal.doctor_id}</td>
<td>${withdrawal.doctor_name}</td>
<td>${withdrawal.transfer_admin_name}</td>
<td><%-- <fmt:formatDate type="date" value="${withdrawal.transfer_date}" /> --%>${withdrawal.transfer_date}</td>
<td>${withdrawal.transfer_reference}</td>
<td class="text-center">
<c:if test="${withdrawal.transferred == true}">
<span class="label label-success">Transferred</span>
</c:if>
<c:if test="${withdrawal.transferred == false}">
<button class="btn btn-warning btn-sm md-trigger" data-modal="form-primary" type="button">Pending</button>
</c:if>
<div class="md-modal colored-header danger custom-width md-effect-9" id="form-primary">
<div class="md-content">
<div class="modal-header">
<h3>Confirm Withdrawal Request</h3>
<button type="button" class="close md-close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body form">
<div class="form-group">
<label class="col-sm-3 control-label">Admin Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="adminName" value="${adminName}">
<input type="text" class="form-control" name="id" value="${withdrawal.id}" />
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Transfer Reference</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="transferReference" value="${transferReference}">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-flat md-close" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger btn-flat md-close" name="submitRequest">Submit</button>
</div>
</div>
</div>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</form:form>
I cannot get the ID of which button I selected from view,
<input type = "text"
class = "form-control"
name = "id"
value = "${withdrawal.id}" />
If I use this code
String withdrawalId = request.getParameter("id");
The value is always 120.
For example:
How do I get the correct ID when I click the modal window?
It seems that the problem is in Nifty Modal Window Effects you are using for popup. It opens modal window for the last row.
It can be fixed with following jsp modifications.
Move modal window declaration out of table. Make it single for page. And rename id field to make it unique, e.g. transferredId
Add onclick to buttons opening modal window in order to init it (set transferredId and others) with necessary values
So your form would be (just ending to save space)
....
<td class="text-center">
....
<c:if test="${withdrawal.transferred == false}">
<button class="btn btn-warning btn-sm md-trigger" data-modal="form-primary" type="button"
onclick="document.getElementById('transferredId').value=${withdrawal.id}">
Pending
</button>
</c:if>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<div class="md-modal colored-header danger custom-width md-effect-9" id="form-primary">
<div class="md-content">
<div class="modal-header">
<h3>Confirm Withdrawal Request</h3>
<button type="button" class="close md-close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body form">
<div class="form-group">
<label class="col-sm-3 control-label">Admin Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="adminName" value="${adminName}">
<input type="text" class="form-control" name="transferredId" id="transferredId" />
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Transfer Reference</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="transferReference">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-flat md-close" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger btn-flat md-close" name="submitRequest">Submit</button>
</div>
</div>
</div>
After that String withdrawalId = request.getParameter("transferredId"); will return correct id.
Excuse me for not add this as a comment, as i can't because i still not have 50 reputation (still 16), i just want you to test something, try to refresh the page, and open row with ID 119 for example first time, i mean any Id rather than 120, and see what happen, if the value that you opened first time is always still exist, so the problem is not in id 120 and the problem is that u may use if not null to set the value some where, so first time it will be null and the value added to it, but next times it will have a value already so u can't change it, and if u can't solve the problem after doing that, please upload your controller so we can detect the problem
Check the generated HTML. Looks to me that it contains listWithdrawals.length instances of that <input and all of them have the same name.
request.getParameter("id") is going to return a single value, not a list of all the values. What you need is request.getParamaterValues("id") that is going to return all of them.
This is because when the form is submitted all those input values are going to be sent.
So the simple solution (with no JavaScript magic) is to get all the lists of values with request.getParamaterValues and deal with everything that changed. ids[0] and transferReferences[0] would be the needed values for the first item in listWithdrawals:
String[] ids = request.getParamaterValues("id");
String[] transferReferences = request.getParamaterValues("transferReference");
for (int i = 0; i < ids.length; i++) {
System.out.println(ids[i]);
System.out.println(transferReferences[i]);
}
Another solution would be to generate unique names for each input/item in listWithdrawals:
<c:forEach var="withdrawal" items="${listWithdrawals}" varStatus="loopStatus">
<input type="text" class="form-control" name="${'transferReference_'.concat(withdrawal.id)}" value="${withdrawal.id}" />
</c:forEach>
And then you'd be able to access the transferReference value of a withdrawal with ID 119 like this:
request.getParameter("transferReference_119")

Spring MVC Multiple ModelAttribute On the Same Form

I have a form with two ModelAttributes one is citizens and the other is punishment. The two objects are separated by jquery tabs. I am having problems in getting the items on the form to display properly some are being displayed and some are not. I mean the html elements.
I am not sure how the Controller would look when there is multiple ModleAttributes on the page. Under is a sample of the code:
Page
<title>Citizen Registration</title>
</head>
<body>
<div id="tabs">
<ul>
<li>Citizen Registration</li>
<li>Punishment</li>
</ul>
<div id="tab1">
<form:form id="citizenRegistration" name ="citizenRegistration" method="post" modelAttribute="citizens" action="citizen_registration.htm">
<div id="divRight" class="mainDiv">
<div class="divGroup" id="divCharInfo">
<fieldset>
<legend>Characteristics Info</legend>
<ol>
<li><form:label for="photo" path="photo">Select Photo</form:label>
<form:input path="photo" type="file" id="photo" title="Upload a photo"/><form:errors path="photo" id="errors"/></li>
<li>
<label>Select Gender</label>
<form:select path="genderId" id="genderId" title="Select Your Gender">
<form:options items = "${gender.genderList}" itemValue="genderId" itemLabel="genderDesc" />
</form:select>
<form:errors path="genderId" class="errors"/>
</li>
<li><form:label for="weight" path="weight">Enter Weight <i>(lbs)</i></form:label>
<form:input path="weight" id="weight" title="Enter Weight"/><form:errors path="weight" id="errors"/>
</li>
<li><form:label for="height" path="height">Enter Height <i>(feet)</i></form:label>
<form:input path="height" id="height" title="Enter Height"/><form:errors path="height" id="errors"/>
</li>
.......................
<div id="tab2">
<form:form id="punishmentRegistration" name ="punishmentRegistration" method="post" modelAttribute="punishment" action="punishment_registration.htm">
<ol>
<li>
<form:label for ="punishmentId" path="punishmentId">Punishment Number</form:label>
<form:input path="punishmentId" id="punishmentId"/><form:errors path="punishmentId" id="errors"/>
</li>
<li>
<form:label for="crimeRecNo" path="crimeRecNo">Select Crime</form:label>
<form:select path="crimeRecNo" id="CrimeRecNo" title="Select Crime">
<form:options items = "${crime.crimeList}" itemValue="crimeRecNo" itemLabel="crimeRecNo" title="crimeDesc"/>
</form:select>
<form:errors path="crimeRecNo" id="errors"/>
</li>
<li>
<form:label for ="monitoringStDate" path="monitoringStDate"> Start Date </form:label>
<form:input path="monitoringStDate" id="monitoringStDate"/><form:errors path="monitoringStDate" id="errors"/>
</li>
<li>
<form:label for ="monitoringEnDate" path="monitoringEnDate"> End Date </form:label>
<form:input path="monitoringEnDate" id="monitoringEnDate"/><form:errors path="monitoringEnDate" id="errors"/>
</li>
</ol>
</form:form>
</div>
</div>
</body>
</html>
Controller
#RequestMapping(value="citizen_registration.htm", method = RequestMethod.GET)
public ModelAndView loadPage(HttpServletRequest request,
HttpServletResponse response,
#ModelAttribute Citizens citizens, #ModelAttribute Punishment punishment,
BindingResult result,
ModelMap m, Model model) throws Exception {
//code here
return new ModelAndView("citizen_registration");
This is my code however when i run it nothing in tab2 is displayed andnot all elements in tab1 is shown.
I don't think so if you can bind multiple models using the Spring form. In fact you should take a look in the spring binding form.
http://static.springsource.org/spring/docs/1.1.5/taglib/tag/BindTag.html
Take a look in the sample code. I have not tested the code. Let know in case of any issues.
Model
public class User{
private String username;
private String password;
..Setter and Getters
}
public class UserProfile{
private String firstName;
private String lastName;
setter and getter
}
Controller
#Controller
public class MyController{
#RequestMapping(....)
public String newAccountForm(ModelMap map){
User user = new User(); //Would recommend using spring container to create objects
UserProfile profile = new UserProfile();
map.addAttribute('user', user);
map.addAttribute('profile', profile);
return "form"
}
#RequestMapping(....)
public String newAccountForm(#ModelAttrbite('User')User user, BindingResult resultUser, #ModelAttribute('UserProfile')UserProfile userProfile, BindingResult resultProfile){
//Check the binding result for each model. If not valid return the form page again
//Further processing as required.
}
}
JSP
<%#taglib uri="http://www.springframework.org/tags" prefix="spring">
<form action="" method="post">
<spring:bind path="user.username">
<input type="text" name="${status.expression}" value="${status.value}"><br />
</spring:bind>
<spring:bind path="user.password">
<input type="password" name="${status.expression}" value="${status.value}"><br />
</spring:bind>
<spring:bind path="profile.firstName">
<input type="text" name="${status.expression}" value="${status.value}"><br />
</spring:bind>
<spring:bind path="profile.lastName">
<input type="text" name="${status.expression}" value="${status.value}"><br />
</spring:bind>
<input type="submit" value="Create"/>
</form>
I already gave alternate approach in this link here
<form:form method="POST" modelAttribute="applicationGeneralInformation">
<div class="section2">
<h2>General Informaion</h2>
<form:input type="hidden" path="id" id="id"/>
<label for="app_version">Version</label>: <form:input type="text" id="app_version" path="version"/><br/>
<label for="app_func_desc">Description</label>: <form:input type="text" id="app_func_desc"
path="functionalDescription"/><br/>
<label for="app_sec_func">Functions</label>: <form:input type="text" id="app_sec_func"
path="securityFunctions"/><br/>
</div>
<div class="section2">
<h2>Application Content</h2>
<form:form method="POST" modelAttribute="applicationContent">
<div>
<h3>CIA Rating</h3>
<label for="CIARating">CIA Rating</label>: <form:select type="text" id="CIARating" path="CIARating">
<form:option value="1">1</form:option>
<form:option value="2">2</form:option>
<form:option value="3">3</form:option>
<form:option value="4">4</form:option>
</form:select><br/><br/>
</div>
<div>
<h3>Business Continuity and Disaster Recovery</h3>
<div>
<h4>RTO</h4>
<label for="RTO">RTO</label>: <form:select type="text" id="RTO" path="RTO">
<form:option value="1">< 2<sub>Hrs</sub></form:option>
<form:option value="2">2<sub>Hrs</sub>-4<sub>Hrs</sub> </form:option>
<form:option value="3">4<sub>Hrs</sub>-48<sub>Hrs</sub></form:option>
<form:option value="4">> 48<sub>Hrs</sub></form:option>
</form:select><br/>
</div>
<div>
<h4>RPO</h4>
<label for="RPO">RPO</label>: <form:input type="text" id="RPO" path="RPO"/><br/>
</div>
</div>
</form:form>
<input type="submit" value="Submit">
</div>
</form:form>
<script type="text/javascript">
$(document).ready(
function() {
$("#userAttendance").submit(
function(e) {
e.preventDefault();
jQuery.ajaxSetup({
async : false
});
var a = "${pageContext.request.contextPath}";
alert(a);
$.post($(this).attr("action"), $(this).serialize(),
function(response) {
$("#showTableByDate").html(response);
jQuery.ajaxSetup({
async : true
});
});
});
//Date picker
$('#datepicker').datepicker({
autoclose : true
});
});

Categories