I have tried to solve the problem since 3 days now, but I can´t.
Actually I want to update a row, but instead of the update the .merge() makes a insert.
The Id is autogenerated from the mySql database.
This is the first button to call the formular, with the id from the prior persisted Report:
<a th:href="#{|/reports/updateForm/${reportId}|}">
<button class="button btn-default btn-xs pull-right" type="button" th:title="#{report.formEdit}">
<i class="fa fa-edit fa-fw"></i></button></a>
This is the aspect which should call the view updateformular:
#RequestMapping(value = "/updateForm/{id}", produces = "text/html", method = RequestMethod.GET)
public String ReportController.updateForm(#PathVariable("id") long id, Model model) {
CRMReport newCRMReport = CRMReport.findCRMReport(id);
model.addAttribute("newCRMReport", newCRMReport);
return "reports/update";
}
Excerpt of view update:
<form action="#" class="form" role="form"
th:object="${newCRMReport}" th:action="#{/reports/update/}"
th:method="put">
<div class="modal-body col-lg-6 form-left">
<div class="panel panel-info">
<div class="panel-heading">
<i th:text="#{report.info}"></i>
</div>
</div>
//Example of the send data fields
<div class="form-group" th:classappend="${#fields.hasErrors('projectState')} ? error">
<label for="projectState" th:text="#{report.projectstatus}"></label>
<select class="form-control" id="projectState" th:field="*{projectState}"
th:size="${pros.length}" multiple="multiple">
<option th:each="pro : ${pros}" th:value="${{pro}}" th:field="*{projectState}" th:text="${pro}"></option>
</select>
</div>
<div class="form-group">
<div>
<input type="hidden" th:field="*{id}" class="form-control" id="id"/>
</div>
</div>
<div class="modal-footer col-lg-12">
<button name="action" value="cancel" type="submit"
class="btn btn-default pull-right">
<i class="fa fa-times fa-fw"></i>
<i th:text="' '+#{report.cancel}"></i>
</button>
<button name="action" value="save" type="submit"
class="btn btn-primary pull-right">
<i class="fa fa-save fa-fw"></i>
<i th:text="' '+#{report.show}"></i>
</button>
</div>
The last thing shoud be an merge(update) of the previus send object newCRMReport:
#RequestMapping(value = "/update", produces = "text/html", method = RequestMethod.PUT, params = "action=save")
public String ReportController.updateReport(#Valid #ModelAttribute("newCRMReport") CRMReport newCRMReport,
BindingResult result, Model model, SessionStatus status) {
// ID will be x, from the prior object
System.out.println("id before: " + newCRMReport.getId());
status.setComplete();
newCRMReport = newCRMReport.merge();
// ID will be x+1, from the new object
System.out.println("id then: " + newCRMReport.getId());
return "redirect:/reports/list/" + newCRMReport.getId();
}
This is the object to update:
#RooJavaBean
#RooToString
#RooJpaActiveRecord(table = "crm_report")
public class CRMReport{
private String projectState;
private String sector;
private String location;
private String client;
private String company;
#JoinColumn
#ManyToOne
private CRMUser responsible;
private String relevance;
private String volumeFrom;
private String volumeTo;
private String chance;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
private Date dateFrom;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
private Date dateTo;
private String timeSpanFrom;
private String timeSpanTo;
#JoinColumn
#ManyToOne
private CRMUser createdBy;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(style = "M-")
private Date createdAt;
}
Can you please help me? Do you know why it performs an insert instead of update it?
Greetings
Loopek (:
I think the problem might be related to this block:
<div class="form-group">
<div>
<input type="hidden" th:field="*{id}" class="form-control" id="id" th:value="${{reportId}}"/>
<span class="help-inline" th:errors="*{id}">[error]</span>
</div>
</div>
First of all, for a hidden input field you won't show any validation error messages, so remove everything but the hidden input field itself.
Next, you are making an association between the input field and the id property of the newCRMReport object instance using the th:field="*{id}" attribute. But you are using also the th:value="${{reportId}} attribute, with a value (reportId) which I think is not available in the view model. That will end with a null or empty value in the id field.
Try replacing the previous block with the following one. Then check if the generated HTML is valid and the hidden field contains the id value.
<input type="hidden" th:field="*{id}" />
Thank you all for your comments and answers. With your annotations I found out the answer.
I have now added the version, with the type:"hidden" to the update view.
<div class="form-group">
<div>
<input type="hidden" th:field="*{version}"
class="form-control" id="version"/>
</div>
</div>
The merge then performs an update.
Related
I have a form for adding products written in HTML and thymeleaf.
<form th:action="#{/products/get}" th:object="${form}" method="post">
<div id="fields">
<label for="name"></label><input type="text" id="name" name="name" autofocus="autofocus" placeholder="NAME" required/><br>
<label for="label"></label><input type="text" id="label" name="label" autofocus="autofocus" placeholder="LABEL" required/><br>
Below the form, there is a button that adds two input fields to the form every time it's pressed. New input fields are the same as those two input fields above. The idea is that the user can enter data for as many products as he wants using the same form. For example, after pressing the button once the form will look like that:
<form th:action="#{/products/get}" th:object="${form}" method="post">
<div id="fields">
<label for="name"></label><input type="text" id="name" name="name" autofocus="autofocus" placeholder="NAME" required/><br>
<label for="label"></label><input type="text" id="label" name="label" autofocus="autofocus" placeholder="LABEL" required/><br>
<label for="name"></label><input type="text" id="name" name="name" autofocus="autofocus" placeholder="NAME" required/><br>
<label for="label"></label><input type="text" id="label" name="label" autofocus="autofocus" placeholder="LABEL" required/><br>
The thing is I'd like to create ArrayList of class ProductForm using the values from input fields and then pass it to my controller using #ModelAttribute.
public class ProductForm{
private String name;
private String label;
//getters and setters
}
Then created a class that wraps ProductForm into ArrayList
public class ProductFormArray {
ArrayList<ProductForm> forms;
//getters and setters
}
And a Controller
#Controller
#RequestMapping(value = "/products")
public class CreateAccountControllerTemporary {
#RequestMapping(value = "/get", method = RequestMethod.POST)
public String createAccount(#ModelAttribute(name = "form")ProductFormArray form){
//some code
}}
My problem is that I can't figure out how to add objects to form ArrayList using values from input fields? Is that even possible? How should I change my HTML file?
It is certainly possible, I explain this on pages 361 to 389 in my book Taming Thymeleaf.
You can check out the sources of the book for free at https://github.com/wimdeblauwe/taming-thymeleaf-sources/tree/main/chapter16
It is hard to summarize 30 pages into a stackoverflow answer, but briefly, check out:
CreateTeamFormData.java: This is similar to your ProductFormArray class. I do use an array instead of an ArrayList.
public class CreateTeamFormData {
#NotBlank
#Size(max = 100)
private String name;
#NotNull
private UserId coachId;
#NotNull
#Size(min = 1)
#Valid
private TeamPlayerFormData[] players;
TeamPlayerFormData.java: This is similar to your ProductForm class.
public class TeamPlayerFormData {
#NotNull
private UserId playerId;
#NotNull
private PlayerPosition position;
TeamController.java: This the controller that uses the CreateTeamFormData.
#GetMapping("/create")
#Secured("ROLE_ADMIN")
public String createTeamForm(Model model) {
model.addAttribute("team", new CreateTeamFormData());
model.addAttribute("users", userService.getAllUsersNameAndId());
model.addAttribute("positions", PlayerPosition.values()); //<.>
return "teams/edit";
}
#PostMapping("/create")
#Secured("ROLE_ADMIN")
public String doCreateTeam(#Valid #ModelAttribute("team") CreateTeamFormData formData,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("editMode", EditMode.CREATE);
model.addAttribute("users", userService.getAllUsersNameAndId());
model.addAttribute("positions", PlayerPosition.values());
return "teams/edit";
}
service.createTeam(formData.toParameters());
return "redirect:/teams";
}
edit.html -> This is the Thymeleaf template. Note that I am using a Thymeleaf fragment edit-teamplayer-fragment for the part of the form that repeats itself (So the name and label fields in your case)
<h3>Players</h3>
<div class="col-span-6 ml-4">
<div id="teamplayer-forms"
th:data-teamplayers-count="${team.players.length}"> <!--.-->
<th:block th:each="player, iter : ${team.players}">
<div th:replace="teams/edit-teamplayer-fragment :: teamplayer-form(index=${iter.index}, teamObjectName='team')"></div>
<!--.-->
</th:block>
</div>
<div class="mt-4">
<a href="#"
class="py-2 px-4 border border-gray-300 rounded-md text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800"
id="add-extra-teamplayer-form-button"
th:text="#{team.player.add.extra}"
#click="addExtraTeamPlayerForm()"
></a> <!--.-->
</div>
</div>
edit-teamplayer-fragment.html: Here is the important part where you need to keep track of the index for each fragment:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
lang="en">
<!-- tag::main[] -->
<div th:fragment="teamplayer-form"
class="col-span-6 flex items-stretch"
th:id="${'teamplayer-form-section-' + __${index}__}"
th:object="${__${teamObjectName}__}"> <!--.-->
<!-- end::main[] -->
<div class="grid grid-cols-1 row-gap-6 col-gap-4 sm:grid-cols-6">
<div class="sm:col-span-2">
<div class="mt-1 rounded-md shadow-sm">
<select class="form-select block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"
th:field="*{players[__${index}__].playerId}">
<option th:each="user : ${users}"
th:text="${user.userName.fullName}"
th:value="${user.id.asString()}">
</select>
</div>
</div>
<div class="sm:col-span-2">
<div class="mt-1 rounded-md shadow-sm">
<select class="form-select block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"
th:field="*{players[__${index}__].position}">
<option th:each="position : ${positions}"
th:text="#{'PlayerPosition.' + ${position}}"
th:value="${position}">
</select>
</div>
</div>
<!-- tag::delete[] -->
<div class="ml-1 sm:col-span-2 flex items-center text-green-600 hover:text-green-900">
<div class="h-6 w-6">
<svg th:replace="trash"></svg>
</div>
<a href="#"
class="ml-1"
th:text="#{team.player.remove}"
x-data
th:attr="data-formindex=__${index}__"
#click="removeTeamPlayerForm($el.dataset.formindex)"> <!--.-->
</a>
</div>
<!-- end::delete[] -->
</div>
</div>
</html>
I am creating an Spring Boot App, in which the user can create licences. The user can type the name, purchaseDate, renewalDate and expirationDate.
My problem is, that when I try to save the data, it returns null for the name, the purchaseDate, renewalDate and expirationDate.
I absolutely don't know what to do anymore, please help. The "// Comment" values in the Model:Licence are those who get null when executing the post.
Model: Licence
#Entity
#Table(name = "TBL_LICENCES")
public class Licence {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String licenceName; // --> null after the post
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String purchaseDate; // --> null after the post
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String renewalDate; // --> null after the post
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String expirationDate; // --> null after the post
public Licence() {}
public Licence(Long id, String licenceName, String purchaseDate, String renewalDate, String expirationDate) {
Id = id;
this.licenceName = licenceName;
this.purchaseDate = purchaseDate;
this.renewalDate = renewalDate;
this.expirationDate = expirationDate;
}
// Getter and Setter
}
Model: LicenceRepository
#Repository
public interface LicenceRepository extends CrudRepository<Licence, Long> { }
Service: LicenceService
#Service
public class LicenceService {
#Autowired
private LicenceRepository licenceRepository;
public List<Licence> getLicences() {
return (List<Licence>) licenceRepository.findAll();
}
public Optional<Licence> getLicenceById(Long id) {
return licenceRepository.findById(id);
}
public void addLicence(Licence licence) {
licenceRepository.save(licence);
}
public void updateLicence(Licence licence) {
licenceRepository.save(licence);
}
public void deleteLicenceById(Long id) {
licenceRepository.deleteById(id);
}
}
Controller: LicenceController
#Controller
public class LicenceController {
#Autowired
private LicenceService licenceService;
#GetMapping("/licences")
public String getLicences(Model model) {
model.addAttribute("licences", licenceService.getLicences());
return "licences";
}
#GetMapping("/onelicence")
#ResponseBody
public Optional<Licence> getLicenceByID(Long id, Model model) {
model.addAttribute("onelicence", licenceService.getLicenceById(id));
return licenceService.getLicenceById(id);
}
#RequestMapping(value="/save", method = {RequestMethod.POST, RequestMethod.PUT, RequestMethod.GET})
public String updateLicence(Licence licence) {
licenceService.updateLicence(licence);
return "redirect:/licences";
}
**// Is performed, when clicking "New Licence > Save"**
#RequestMapping(value="/addNew", method = {RequestMethod.POST, RequestMethod.PUT, RequestMethod.GET})
public String addLicence(Licence licence) {
licenceService.addLicence(licence);
return "redirect:/licences";
}
#RequestMapping(value="/delete", method = {RequestMethod.DELETE, RequestMethod.PUT, RequestMethod.GET})
public String deleteLicence(Long id) {
licenceService.deleteLicenceById(id);
return "redirect:/licences";
}
}
licences.html
<!DOCTYPE html>
<html lang="de" xmlns="http://www.w3.org/1999/html"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<script type ="text/javascript" src="webjars/jquery/3.4.1/jquery.min.js"></script>
<script type ="text/javascript" src="webjars/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<link href="webjars/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<title>Licence</title>
</head>
<body>
<div class = "container">
<h2>Licences</h2>
<table class = "table table-striped">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Kaufdatum</td>
<td>Erneuerungsdatum:</td>
<td>Auslaufdatum:</td>
</tr>
</thead>
<tbody>
<tr th:each = "licence: ${licences}">
<td th:text="${licence.id}">ID</td>
<td th:text="${licence.licenceName}">Name</td>
<td th:text="${licence.purchaseDate}">Kaufdatum</td>
<td th:text="${licence.renewalDate}">Erneuerungsdatum</td>
<td th:text="${licence.expirationDate}">Auslaufdatum</td>
<td><a class="btn btn-warning">Edit</a></td>
<td><a class="btn btn-danger">Delete</a></td>
</tr>
</tbody>
</table>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addModal" data-whatever="#mdo">New Licence</button>
</div>
// Bootstrap Varying Modal Content
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<form th:action="#{/addNew}" method ="post">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New Licence</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="name" class="col-form-label">Lizenz Name</label>
<input type="text" class="form-control" id="licenceName" name="name">
</div>
<div class="form-group">
<label for="purchase" class="col-form-label">purchaseDate</label>
<input type="date" class="form-control" id="purchaseDate" name="purchase">
</div>
<div class="form-group">
<label for="renewalAdd" class="col-form-label">renewalDate</label>
<input type="date" class="form-control" id="renewalAdd" name="renewal">
</div>
<div class="form-group">
<label for="expirationAdd" class="col-form-label">expirationDate</label>
<input type="date" class="form-control" id="expirationAdd" name="expiration">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
schema.sql
DROP TABLE IF EXISTS TBL_LICENCES;
CREATE TABLE TBL_LICENCES (
id INT AUTO_INCREMENT PRIMARY KEY,
licence_name VARCHAR(250),
purchase_date VARCHAR(250),
renewal_date VARCHAR(250),
expiration_date VARCHAR(250)
);
data.sql --> This works and the data is shown.
INSERT INTO
TBL_LICENCES (licence_name, purchase_date, renewal_date, expiration_date)
VALUES
('Test1', '2020-01-31', '2020-06-31', '2020-12-31'),
('Test', '2021-01-31', '2021-06-31', '2021-12-31');
Properties: application.properties
spring.h2.console.enabled=true
spring.datasource.platform=h2
spring.datasource.url=jdbc:h2:mem:<dbLicences>
spring.jpa.hibernate.ddl-auto=update
The name attribute of the input control should match the name of the fields in the Licence class. Currently your id attribute is matching the name of the fields, but when a form is submitted it uses the name attribute to build the request parameters.
Update your HTML to match something like:
<input type="text" class="form-control" id="licenceName" name="licenceName" />
Fix the name for other fields and you will have the Licence object populated with data from the form.
Also, I see that
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String licenceName;
licenceName is annotated with #DateTimeFormat. I guess this is a mistake, please correct that as well.
I have a form which looks like this:
<form th:action="#{/viewExpenses}" method="post" class="form-horizontal">
<div class="form-group">
<label for="date" class="control-label col-md-3">Date:-</label>
<div class="col-md-9">
<input type="date" class="form-control" id="date" th:name="date"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-3 col-md-4">
<button class="btn btn-primary">View Details</button>
</div>
</div>
</form>
Now when I submit this form I wish to get the date value as LocalDate. So on my controller I did:
#RequestMapping(value = "/viewExpenses", method = RequestMethod.POST)
public String expenseDetails(Model model, #RequestParam("date")
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
BigDecimal totalExpense = new BigDecimal(0);
List<Expenditure> e = expenditureService.viewExpenseDetails(date);
for (Expenditure exp : e) {
totalExpense = totalExpense.add(exp.getAmount());
}
model.addAttribute("showExpenditure", true);
model.addAttribute("totalExpense", totalExpense);
model.addAttribute("expenses", e);
return "finance/expensedetails";
}
For now I get date value in my controller as null. I have tried changing pattern of #DateTimeFormat but it is still not working.
what might be the correct way to receive date parameter?
This looks like the binding here is not happening.you can try using spring:form tag and bind the controller object via modelAttribute.
I'm creating a simple CRUD in Spring Boot+Thymeleaf and all other CRUD on application work well but this one. When I submit the form, the object comes with empty attributes to controller.
In the following, the code:
Artist.java
#Entity
public class Artist {
#Id
#GeneratedValue
private Long id;
#Column(nullable=false, length = 80)
private String artistName;
<getters and setters>
ArtistController.java
#Controller
public class ArtistController {
#Autowired
ArtistRepository artistRepository;
#GetMapping("/artist/add")
public String addArtist(Model model) {
model.addAttribute("artist", new Artist());
return "artist/form_artist";
}
#PostMapping("/artist/save")
public String artistSave(#ModelAttribute(name="artist") Artist artist) {
artistRepository.save(artist);
return "redirect:/artist";
}
}
And now, the form:
<form action="#" th:action="#{/artist/save}" th:object="${artist}" method="post" class="form-horizontal">
<div class="form-group">
<label for="id" >HobbyOn id:</label>
<input type="text" id="id" th:field="*{id}" readonly="readonly" class="form-control" placeholder="hobbyOn ID" />
</div>
<div class="form-group">
<label for="artistName" >Artist Name:</label>
<input type="text" th:field="*{artistName}" class="form-control" required="required" />
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value="Submit" />
</div>
</form>
I can't see any difference from examples in internet and in my own code. Any help will be very welcomed.
java.lang.IllegalStateException: Neither BindingResult nor plain target object in ajax call
I am using Thymeleaf and Spring MVC and I am having some problems with a dynamic form.
I have a form with a selector, and when this changed, I do an Ajax call, which should show another selector and a field.
I have these objects:
public class SaleMini{
private int businessId;
private int sellerId;
private int productId;
private int amount;
private int row;
private String date;
private List<SaleItem> item;
//getters and setters
}
public class SaleItem{
private int productId;
private int amount;
private boolean gift;
private List<Integer> components;
private List<Composition> compositionList;
//getters and setters
}
My html code is:
<form id="sales" action="#" th:action="#{/sales/add}" method="post">
<div class="row">
<div class="form-group col-md-6">
<label class="label-control" th:text="#{label.equipment}"></label>
<select th:field="${sales.businessId}" class="form-control" onchange="submitData()"> <!--- Equipment List --->
<option th:each="e : ${equipmentList}" th:value="${e.id}" th:text="${e.name}"></option>
</select>
</div>
<div class="form-group col-md-6">
<label class="label-control" th:text="#{label.seller}"></label>
<select th:field="${sales.sellerId}" class="form-control">
<option th:each="s : ${sellerList}" th:value="${s.id}" th:text="${s.name + ' ' + s.surname}"></option>
</select>
</div>
</div>
<div id="product-panel" class="row" >
<div th:fragment="resultsList">
<div th:each="i,rowStat : ${itemList}">
<p th:text="${i.productId}"></p>
<select class="form-control products_select" th:field="${i.productId}" th:onchange="${'javascript:callComposed(' + rowStat.index + ')'}" >
<option value="0" >Select Product</option>
<option th:each="p : ${productList}" th:value="${p.id}" th:text="${p.name}" th:attr="data-compound=${p.compound},data-generic=${p.genericId}"></option>
</select>
</div>
<a class="btn btn-action" id="btn-add" onclick="submitData()" style="margin-top: 25px !important;"><span class="fa fa-plus fa-btn"></span></a> <!--I should add as many product as I wanted-->
</div>
</div>
<div class="row">
<div class="form-btn">
<input type="submit" th:value="#{label.save.sale}" class="btn btn-custom"/>
</div>
</div>
</form>
When the Equipment List is change, I do an ajax call
function submitData(){
$.ajax({
'url': 'sales/addRow',
'type': 'POST',
'data': $('#sales').serialize(),
'success': function(result){
$("#product-panel" ).html( result );
},
});
}
The function I call on the controller is:
#RequestMapping(value = "/addRow", method = RequestMethod.POST)
public String addRow(#Valid SaleMini sale, BindingResult bindingResult,ModelMap model) {
List<SaleItem> siList = new ArrayList<SaleItem>();
if(sale!=null && sale.getBusinessId()!=0)
{
SaleItem si = new SaleItem();
si.setAmount(1);
siList.add(si);
}
model.addAttribute("itemList", siList);
return folder+"/add :: resultsList";
}
The problem is when I call to submitData().
I can do the call to the controller well (submitData() and then addRow), and it works, but when I get the data I have and error:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'i' available as request attribute
I get data after the call, but I can't access to the data with th:field
In the html part this works (th:text):
<p th:text="${i.productId}"></p>
But this not (th:field), and I don't know why:
<select class="form-control products_select" th:field="${i.productId}" th:onchange="${'javascript:callComposed(' + rowStat.index + ')'}" >
</select>
Thank you in advance
Hi I think you are missing a couple of details in your form. With this th:object="sale" you say what will be the modelAttribute of your form, and to make reference to any attribute of that object just use *{attribute.path}
<form id="sales" action="#" th:action="#{/sales/add}" method="post" th:object="sale">
And to make reference to attributes of your sale object use:
<select th:field="*{businessId}" class="form-control" onchange="submitData()"> <!--- Equipment List --->
<option th:each="e : ${equipmentList}" th:value="${e.id}" th:text="${e.name}"></option>
</select>