Spring: get input button id - spring

I have this html template in thymeleaf.
<table id="listAllAccountantTable" th:cellspacing="0" class="table table-striped table-bordered" style="width:100%;">
<thead>
<tr>
<th>No. </th>
<th>Registered Date</th>
<th>Status</th>
<th>Name</th>
<th>Email</th>
<th>Contact No.</th>
<th>IC No.</th>
<th>IC attachment</th>
<th>Actions </th>
</tr>
<tr th:each="acc,iterationStatus : ${accountantListing}">
<td th:text="${iterationStatus.count}">1</td>
<td th:text="${acc.currentTimeStamp}"></td>
<td th:text="${acc.active}">1</td>
<td th:text="${acc.name}">Name</td>
<td th:text="${acc.email}">Email</td>
<td th:text="${acc.phoneNumber}">Contact No.</td>
<td th:text="${acc.icNumber}">IC No.</td>
<td th:text="${acc.id}"> To be fixed: upload IC image</td>
<td>
<form action="#" data-th-action="#{/accountantApplication}" method="post">
<button type="submit" name="action" th:id="${acc.id}"
value="Accept">Accept</button>
<button type="submit" name="action" th:id="${acc.id}"
value="Reject">Reject</button>
</form>
</td>
</tr>
My Spring controller is:
#RequestMapping(value="/accountantApplication", method=RequestMethod.POST, params="action=Accept")
public ModelAndView Accept() {
ModelAndView modelAndView = new ModelAndView();
System.out.println("######## Accepting accountant");
modelAndView.setViewName("AccountantListing");
return modelAndView;
}
#RequestMapping(value="/accountantApplication", method=RequestMethod.POST, params="action=Reject")
public ModelAndView Reject() {
ModelAndView modelAndView = new ModelAndView();
System.out.println("######## Rejecting accountant");
modelAndView.setViewName("AccountantListing");
return modelAndView;
}
The table shows a list of accountants.
All accountants are loaded from db and displayed on the table.
They need to be accepted or rejected.
When I click the accept button, Accept() is called.
How do I get the ID attached to button?
Or if there is better way of immplementing this. let me know too. Thanks so much

In your form, you should have a hidden input:
<form action="#" data-th-action="#{/accountantApplication}" method="post">
<input type="hidden" name="id" th:value="${acc.id}" />
<button type="submit" name="action" value="Accept">Accept</button>
<button type="submit" name="action" value="Reject">Reject</button>
</form>
Then, in your controllers:
public ModelAndView accept(#RequestParam String id) {
.
.
.
}
public ModelAndView Reject(#RequestParam String id) {
.
.
.
}
Also, as a side note, you can replace:
#RequestMapping(value="/accountantApplication", method=RequestMethod.POST, params="action=Accept")
#RequestMapping(value="/accountantApplication", method=RequestMethod.POST, params="action=Reject")
with
#PostMapping(value="/accountantApplication", params="action=Accept")
#PostMapping(value="/accountantApplication", params="action=Reject")

Related

Delete mapping doesn't work, I'm getting 405 error

I have this controller:
#DeleteMapping("/delete/{id}")
public String deleteWallet(#PathVariable("id") long id, Model model) {
Wallet wallet = walletRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid wallet Id:" + id));
walletRepository.delete(wallet);
model.addAttribute("wallets", walletRepository.findAll());
return "redirect:/";
}
And this is HTML:
<table class="table table-striped table-hover" id="productTable">
<thead>
<tr class="success">
<th>Wallet Name</th>
<th>Initial Balance</th>
</tr>
</thead>
<tbody>
<tr th:each="wallet : ${wallet}">
<td th:text="${wallet.walletName}"></td>
<td th:text="${wallet.initialBalance}"></td>
<td>
<a th:href="#{/api/wallet/delete/{id}(id = ${wallet.id})}">Delete</a>
</td>
</tr>
</tbody>
But when I press delete button its says:
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
I'm confused, my method is #DeleteMapping
Anyway, I found a way:
HTML:
<form th:action="#{/api/wallet/delete/{id}(id=${wallet.id})}"
th:object="${wallet}" method="post">
<input type="hidden" th:field="${wallet}">Delete</input>
<button type="submit" onClick="return confirm('sure?')"/>
</form>
Controller:
#PostMapping("/delete/{id}")
public String deleteWallet(#PathVariable("id") long id, Model model) {
walletService.deleteWalletById(id);
return "redirect:/";
}

Getting the selected values from a checkbox list to the controller with Spring Boot

I'm using Spring Boot with Thymeleaf as viewer, and I want to delete all selected items from a table. Therefore, I need to pass to the controller a list with the values from the selected checkboxes.
This is my approach for the controller:
#PostMapping("/admin/rates/prices/delete")
public String delete(#ModelAttribute Rate price, ServletWebRequest request){
if(request.getParameterValues("idChecked") != null){
for(String idCheckedStr : request.getParameterValues("idChecked")){
int idrate = Integer.getInteger(idCheckedStr);
rateRepository.deleteRate(idrate);
}
}
return "redirect:/admin/rates/prices";
}
I get a Null Pointer Exception:
java.lang.NullPointerException: null
at com.rentalwebs.controllers.rates.PriceListController.delete(PriceListController.java:42)
I think this method should collet the values::
request.getParameterValues("idChecked")
This is the line at the form, which creates each checkbox with the Thymeleaf annotations:
<input type="checkbox" th:name="idChecked" th:value="${price.idrate}"/>
That's the view code for the form:
<form th:action='#{/admin/rates/prices/delete}'
method="POST"
th:object="${rate}">
<button type="submit" name='delete' value="delete"
class='btn btn-secondary btn-sm'
th:text="#{delete}"
data-toggle="tooltip" data-placement="right"
th:title="#{delete.selected}">
</button>
<p></p>
<table class='table table-sm responsive'>
<thead class='thead-default'>
<tr>
<th><input type="checkbox" id="checkAll"/></th>
<th th:text='#{from}'></th>
<th th:text='#{to}'></th>
<th th:text='#{price}'></th>
</tr>
</thead>
<tbody>
<tr th:each="price : ${prices}">
<td>
<input type="checkbox" th:name="idChecked" th:value="${price.idrate}"/>
</td>
<td th:text="${#temporals.format(price.datefrom, 'dd/MM/yyyy')}"></td>
<td th:text="${#temporals.format(price.dateto, 'dd/MM/yyyy')}"></td>
<td th:text="${price.price} + ' €'"></td>
</tr>
</tbody>
</table>
</form>
Thank you in advance for your help :-)
This is the code with the solution, taken from the comments:
#PostMapping("/admin/rates/prices")
public String delete(#RequestParam("idChecked") List<String> idrates){
if(idrates != null){
for(String idrateStr : idrates){
int idrate = Integer.parseInt(idrateStr);
rateRepository.deleteRate(idrate);
}
}
return "redirect:/admin/rates/prices";
}

How to validate movable(portable) application

I'm having trouble with validating one movable app.
When I open the app and fill-up the data, I send this data to the controller. Then validate this data and if any error I wan to show this error on the app without close it. If no error, I proceed to the success page and close the app. So far I manage to create the app and to validate the data, but my problem is that I don't know how to redirect from the controller back to the add without close it and show this error.
My web application is using Spring.
Here is some of my code:
This is how I init my index page:
#RequestMapping(value="/index", method=RequestMethod.GET)
public ModelAndView initializeForm(ModelMap model){
ModelAndView result = new ModelAndView("index.jsp");
result.addObject("loginInfo", new LoginInfo());
return result;
}
This is what happen when submit the data from the movable app:
Here I wan when there is an error, to redirect to the same app without close it.
#RequestMapping(value="/welcome", method=RequestMethod.GET)
public String onSubmit(#ModelAttribute("loginInfo") #Valid LoginInfo logInfo,
BindingResult result, ModelMap model){
if(result.hasErrors()){
return "";//here I need to redirect to the movable app form.
}
return "redirect:login.htm";
}
Here is my jsp:
<form:form action="welcome" method="GET" id="mainLogForm" commandName="loginInfo">
<div id="loginForm" class="ui-widget-content" >
<table align="right" width="300" cellpadding="0">
<tr><td align="right"><input type="button" id="cancelButton" value="x" onclick="showHide('loginForm')"/></td></tr>
</table>
<table align="center" width="300" bgcolor="f8f8ff" border="1" cellspacing="0" cellpadding="5" >
<tr>
<td align="right" width="100">User:</td>
<td width="100"><form:input path="username" /></td>
<td width="100"><form:errors path="username" cssClass="error"/></td>
</tr>
<tr>
<td align="right" width="100">Password:</td>
<td width="100"><form:input path="password" type="password"/></td>
<td width="100"><form:errors path="password" cssClass="error"/></td>
</tr>
</table>
<br>
<input type="submit" id="logInButton" align="center" value="SignIn" onclick="submitForm()" />
</div>
</form:form>
Thanks in advice!

share 'form fragment' between createForm.html, updateForm.html on thymeleaf

I use thymeleaf on spring.
I don't want to produce duplicated html page createForm.html and updateForm.html.
Maybe It requires copy & paste.
My code is below.
<form class="form-horizontal" role="form" th:action="${!template.new#{/templates}" method="post"
th:object="${template}">
...
</form>
When template is before saving(=create), action is '/templates'.
When tempalte is after saving(=update), action is '/templates/UUID/edit'.
=> It is rails convention.
You can also add this address to the ModelMap:
modelMap.add("address", "/templates")
th:action="#{${address}}"
HTML
<div class="form-group">
<label for="objectName">Name</label>
<input type="text" class="form-control" th:value="${object.name}" name="name"
id="objectName" placeholder="Name"/>
</div>
bottom HTML
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Name 1</th>
<th>Name 2</th>
<th>Name 3</th>
</tr>
</thead>
<tbody>
<tr data-th-each="eachObject : ${obj}">
<td><a data-th-text="${eachObject.name}" th:href="#PATH/edit?Name=}+${eachObject.name}">...</a></td>
<td data-th-text="${eachObject.name2}">...</td>
<td data-th-text="${eachObject.name3}">...</td>
<td><a th:href="#{/PATH/delete?objname=}+${eachObject.name}">delete</a></td>
</tr>
</tbody>
</table>
</div>
Controller
#RequestMapping(value = "/create",method = RequestMethod.GET)
public String createMethod(Model model) {
Object obj = new Object();
model.addAttribute("Object", obj);
return "htmlpage";
}
controller
#RequestMapping(value = "/form/save", method = RequestMethod.POST)
public String campaignPost(#ModelAttribute("object") Object obj, Principle prin, Model model){
service.save(obj);
}

Values for th:field attributes in checkbox

I have table with datas from database (insert dynamically). In one column I insert checkbox. Now I want to select one of them and send to next form (I select one product and send properties to another form. In this form should be displayed properties only the select product). But I don't know what kind of value insert in th:field="*{}". I tried many solutions but doesn't work. My html form with all products table:
<form action="/oferta/zamow" th:action="#{/oferta/zamow}"
th:object="${oferta}" method="post">
<table border="1" id="display-data">
<tr>
<td>#</td>
<td>title</td>
<td>author</td>
<td>rok</td>
<td>cena</td>
<td></td>
</tr>
<tr th:each="produkt, pozycja : ${oferta}">
<td th:text="${pozycja.count}"></td>
<td><span th:text="${produkt.tytul}"></span></td>
<td><span th:text="${produkt.autor}"></span></td>
<td><span th:text="${produkt.rok}"></span></td>
<td><span th:text="${produkt.cena}"></span></td>
<td>
<input type="submit" value="zamow"/>
<!-- <a th:href="#{/zamowienie}">zamow</a> -->
</td>
<td>
<label>zamow</label>
<input type="checkbox" th:field="*{produkt}" th:value="${produkt}"/>
</td>
</tr>
</table>
</form>
Form to display select product:
<form action="/zamowienie/zam" th:action="#{/zamowienie/zam}"
th:object="${zamowienie}" method="post">
<table border="1" id="display-data">
<tr align="center">
<td colspan="2">twoje zamowienie</td>
</tr>
<tr>
<td>tytul</td>
<td><span th:text="${produkt.tytul}"></span></td>
</tr>
<tr>
<td>autor</td>
<td><span th:text="${produkt.autor}"></span></td>
</tr>
<tr>
<td>rok</td>
<td><span th:text="${produkt.rok}"></span></td>
</tr>
<tr>
<td>cena</td>
<td><span th:text="${produkt.cena}"></span></td>
</tr>
<tr>
<td>data zlozenia zamowienia</td>
<td><span th:text="${datazam}"></span></td>
</tr>
</table>
</form>
Thanks for help.
I am not sure if this is the answer you seek, but you can find an example at http://www.thymeleaf.org/doc/html/Thymeleaf-Spring3.html#checkbox-fields.
Here is a simple example to illustrate how to use a checkbox in Thymeleaf with Spring MVC.
Controller:
#RequestMapping(value = "/showForm", method=RequestMethod.GET)
public String showForm(Model model) {
List<String> allItems = new ArrayList<String>();
allItems.add("value1");
allItems.add("value2");
allItems.add("value3");
model.addAttribute("allItems", allItems);
Foo foo = new Foo();
List<String> checkedItems = new ArrayList<String>();
// value1 will be checked by default.
checkedItems.add("value1");
foo.setCheckedItems(checkedItems);
model.addAttribute("foo", foo);
...
}
#RequestMapping(value = "/processForm", method=RequestMethod.POST)
public String processForm(#ModelAttribute(value="foo") Foo foo) {
// Get value of checked item.
List<String> checkedItems = foo.getCheckedItems();
...
}
html:
<form action="#" th:action="#{/processForm}" th:object="${foo}" method="post">
<div th:each="item : ${allItems}">
<input type="checkbox" th:field="*{checkedItems}" th:value="${item}" />
<label th:text="${item}">example</label>
</div>
<input type="submit" />
</form>
Foo.java:
public class Foo {
private List<String> checkedItems;
public List<String> getCheckedItems() {
return checkedItems;
}
public void setCheckedItems(List<String> checkedItems) {
this.checkedItems = checkedItems;
}
}
Hope this helps.
Take a look at the thymeleaf spring integration docs.
All th:field are mapped against the command object. Thats why you need the *{} expression.
One thing the template engine is not able to do (yet) is mapping fields inside a loop directly. So you cannot use the *{} approach to reference the produkt variable from the loop.
What you have to do is use the index of the th:each expression and build a property accessor with a pre-evaluated expression for the index.
<input type="checkbox" th:field="*{produkts[__${index}__].checked" />
You do not need the th:value, th:field is taking care of it. (Except if you want to superseed it)

Resources