How to set link in onClick method in thymeleaf? - java

When I do a project with jsp, I try to keep it simple. Now I wanted to do project in Thymeleaf. I wanted to show a confirm dialogue box before deleting. I did it. But while I click ok I get an error. I think I cannot set a link properly inside the onclick method.
Here is my html code:
<tr th:each="student,iterStat : ${studentList}">
<td th:text="${student.id}"></td>
<td th:text="${student.roll}"></td>
<td th:text="${student.firstName}"></td>
<td th:text="${student.lastName}"></td>
<td th:text="${student.age}"></td>
<td>
<!-- <a th:href="#{/deleteStudent/(id=${student.id})}">Delete</a> -->
<a href="#" onclick="confirmRemoveQuestion('#{/deleteStudent/(id=${student.id})}')">
Delete
</a>
</td>
<script>
function confirmRemoveQuestion(link) {
if (show_confirm()) {
window.location = link;
this.hide();
} else {
this.hide();
}
}
function show_confirm() {
return confirm("Are you sure you want to do this?");
}
</script>
</tr>
Here is my Controller:
#RequestMapping(value = "/deleteStudent", method = RequestMethod.GET)
public String deleteStudent(#RequestParam(name="id") int id) {
studentService.deleteStudent(id);
return "redirect:/getStudents";
}
Note: Without dialogue box I can delete an object easily. That code is in comment line.

At last i have fixed it. i have replaced the line
Delete
with
Delete
And i have deleted javascript code. Because it is no longer needed!

Related

What is the difference between View and Redirection in Thymeleaf?

I understand that this question might sound stupid to a few but I am new to Spring Boot and Thymeleaf.
Suppose I am on page1.html currently. The user clicks on some button which generates a POST/GET request to my controller MyController.java that maps this request to some function using #RequestMapping.
After I am done processing the request I return a view name like return "page2" from my controller.
Contents of the page1.html change but the url still remains the same like http://localhost:8080/page1 instead of changing to http://localhost:8080/page2
I know that in order to go to a different page I have to use redirection but why is this not possible with view?
Could someone explain me why does this happen and when should I use redirection or when should I use view?
EDIT 1:
Here is my controller
#RequestMapping (value = "edit", method = RequestMethod.POST, params="action=ADD")
{
public String saveUser(#ModelAttribute UserDto userDto) {
try {
User user = new User();
if(userDto.getId() != null) {
throw new UserExists();
}
user.setName(userDto.getName());
user.setEmail(userDto.getEmail());
System.err.println("Request Recieved");
userDao.save(user);
return "success";
} catch (Exception e) {
System.err.println("Error Saving User");
e.printStackTrace();
return "failure";
}
}
Here is my view
<form id="manipulate-data-form" th:object="${userobj}" method="post" th:action="#{/edit}">
<table id="manipulate" class="table table-bordered">
<tr>
<td>ID</td>
<td><input type="text" class="form-control" th:if="${userobj != null}" th:field="*{id}" ></input></td>
</tr>
<tr>
<td>NAME</td>
<td><input type="text" class="form-control" th:if="${userobj != null}" th:field="*{name}" ></input></td>
</tr>
<tr>
<td>EMAIL</td>
<td><input type="text" class="form-control" th:if="${userobj != null}" th:field="*{email}" ></input></td>
</tr>
<tr>
<td><input name="action" value="ADD" type="submit" class="btn btn-success" ></input></td>
<td>
<input name="action" value="DELETE" type="submit" class="btn btn-danger" ></input>
<input style="margin-left: 30px" name="action" value="UPDATE" type="submit" class="btn btn-primary" ></input>
</td>
</tr>
</table>
</form>
So basically clicking the button it invokes the saveUser() Controller and then when I return the failure or success view the URL remains the same but the contents of the the page change corresponding to success or failure.
Let me try to answer some of your questions:
The contents of the page1.html change but the url still remains the
same like http://localhost:8080/page1 instead of changing to
http://localhost:8080/page2
You are hitting an URL like http://localhost:8080/page1. /page1 does not mean to show your view with the name page1.html. Its more the Url for your #RequesteMapping annotation and which method should be executed for this request.
For example:
Your are hitting the Url:
http://localhost:8080/page1 and your mapping is: #RequestMapping("/page1") and you want return page1.html. So your view is: return "page1";
Now you see the content of your page1.html. Your provided button should now have a link to http://localhost:8080/page2 and your Controller should have a mapping to it #RequestMapping("/page2"). In this method you can return your return "page2" and your Url will change to http://localhost:8080/page2.
And if the link of the button does have another value instead of http://localhost:8080/page2 but you want to show this particular URL of /page2 you need a redirection: return "redirect:/page2" in the method of the particular #RequestMapping("/anyOtherMapping").
Could someone explain me why does this happen and when should I use redirection or when should I use view?
I am not 100% sure if this is correct but I think its just a rule why there is view and redirection. If you want to stand on the particular URL and want to show the view which was build for that, just do it. If you dont want to show the same URL or want to switch to another page, just use redirection.
A redirection also calls a controller again which is correct mapped to your redirections URL and return a view.
Some examples for using redirection are the follows:
after a successful login you can redirect to an users home page.
after saving an item (REST approach) you can redirect to the specific id for this item /item/1 and return a view which includes informations of that item.
Answer for your edit question:
Try to use redirection for changing url.
#RequestMapping (value = "edit", method = RequestMethod.POST, params="action=ADD")
{
public String saveUser(#ModelAttribute UserDto userDto) {
try {
User user = new User();
if(userDto.getId() != null) {
throw new UserExists();
}
user.setName(userDto.getName());
user.setEmail(userDto.getEmail());
System.err.println("Request Recieved");
userDao.save(user);
return "redirect:/success";
} catch (Exception e) {
System.err.println("Error Saving User");
e.printStackTrace();
return "redirect:/failure";
}
}
#RequestMapping("/success")
public String successPage(){
return "success";
}
#RequestMapping("/failure")
public String failurePage(){
return "failure";
}
This should change the URL because you will make a redirection from your /edit to /failure or /success page. You can also give parameters within your redirection if you want.

How to submit a list of checkmark values into a form in Thymeleaf?

I am trying to create a table that displays a list of all logs that have been added. In addition to displaying the info I wanted to have another column of checkboxes that when clicked would allow me to delete them with the corresponding delete button.
The issue that I am having is that I am unable to put the values from my checkboxes into the array of Longs. I also want to keep the functionality of my table as it displays correctly.
For my table I have the following code:
<form method="post" th:action="#{/projects/log/delete/}" th:object="${deleteForm}">
<div th:each="log : ${allLogs}" class="row">
<tbody>
<tr class="active">
<td>
<input type="checkbox" th:field="*{logIds}" th:value="${log.id}" />
</td>
<td th:text="${log.teamUsed}"></td>
<td th:text="${log.opponentStarters}"></td>
<td th:text="${log.opponentOthers}"></td>
<td th:text="${log.myStarters}"></td>
<td th:text="${log.myOthers}"></td>
<td th:text="${log.result}"></td>
</tr>
</tbody>
</div>
<button type="submit" id="deleteButton" class="hidden"></button>
</form>
The form that I am trying to place the checkbox values into is: (log.id is a long)
public class LogDeleteForm {
private List<Long> logIds = new ArrayList<>();
public List<Long> getLogIds() {
return logIds;
}
public void setLogIds(List<Long> logIds) {
this.logIds = logIds;
}
}
In my controller I have the following setup for my view:
#RequestMapping(value = "pokemon_log", method = RequestMethod.GET)
public String view(Model model) {
model.addAttribute("addForm", new logForm());
model.addAttribute("deleteForm", new logDeleteForm());
model.addAttribute("allLogs", logService.getAllLogs());
return "log";
}
I am able to implement the deletion fine I am just unable to get the Ids that I would like to delete. How can I get the checkbox values placed into the list of longs?
Turns out that my issue was in my deleteLogs method:
#RequestMapping(value = "/log/delete", method = RequestMethod.POST, params = "delete")
public String deleteLogs(#ModelAttribute("deleteForm") logDeleteForm deleteForm) {
List<Long> formIds = deleteForm.getLogIds();
if (formIds == null || formIds.size() == 0) {
return "redirect:/projects/log";
}
for (Long id : formIds) {
logService.deleteLog(id);
}
return "redirect:/projects/log";
}
My redirects were both "redirect:/log" instead of "redirect:/projects/log"
Also my button was missing name="delete" because it was unable to qualify as a submit with a delete param.

OnClick Event Not Firing Before Spring MVC Controller

I am trying to fire onClick event and Spring controller one by one.
In the click event of the button, I set a hidden field and then I want the controller to be executed AND the hidden field to be available in it. Here is my code for the JSP and the Spring Controller
JSP
<html:hidden property="MenuID" name="MenuID" id="hidMenuID" />
<c:forEach items="${menus}" var="menu" >
<tr class="cartItem">
<td align="left" >${MenuId}</td>
td align="right"><input type="text" name="menu_name" value="${Name}"/></td>
<td align="right"><input type="text" name="menu_price" value="${MenuPrice}"/></td>
<td align="right"><input type="submit" class="button" name="add_menu" value="Add" onclick="return SetMenuID();"></td>
<td align="right"><input type="submit" class="button" name="remove_menu" value="Remove" onclick="return SetMenuID();"></td>
</tr>
</c:forEach>
JavaScript
<script type="text/javascript">
function SetMenuID()
{
var MenuID = document.getElementById('hidMenuID');
MenuID.value = 'The new value';
return true;
}
</script>
Spring MVC
#RequestMapping(params = "add_menu", method = RequestMethod.POST)
public ModelAndView AddMyMenu(#RequestParam("MenuID") String menu_id, Model model, #ModelAttribute("cart") ArrayList<Menu> mycart)
{
int nMenuId = Integer.parseInt(menu_id);
Menu menu = m_arrMenus.get(nMenuId);
model.addAttribute("menus", GetMenus());
mycart.add(menu);
return new ModelAndView("edit_menu");
}
As you might guess, I am populating data from database. I have an onClick function associated with each ADD button. I set hidden field in thid function and want it to be available in my controller. But a runtime exception comes that
Error Status 400 - Required string MenuID is not present
What should I do to achieve similar result ? Thanks for any input.
#RequestParam expects a parameter my name in the request url.
Since your form is submitted and there are no request param that the action recieves. This is a reason you are getting 400 http error from server.
See the difference between #RequestParam vs #PathVariable
So either change the #RequestParam annotation or add (required = false) to it.

Return a list using JQuery

I am using the following JQuery, JSP and Controller to return list of cities upon changing the country drop down menu on my app JSP page, yet I think the dataType, success parameters in the JQuery are not correct as I am not getting back the list. So can someone please tell me what I am doing wrong here and how I can get the list of Cities to add them to the cities drop down menu upon changing the Country drop down menu?
Thanks for your time
<script type="text/javascript">
function loadCity(){
var countryData="countryId="+$(country).val();
$.ajax({
type: "POST",
url: "LoadCities.htm",
data:countryData,
dataType: "javascript",
success: function(cities){
loadCities(eval(cities))
}
});
}
function loadCities(citiesLst){
clearCitiesDD();
for(var i=0;i<citiesLst.length;i++){
var city=citiesLst[i];
appendCity(city.id,city.value);
}
}
function clearCitiesDD(){
$('#cityDD').find('option').remove();
}
function appendCity(id,cityName){
$('#cityDD').append($("<option id='"+id+"'>" + cityName + "</option>"));
}
}
</script>
and in my application controller I have the following code:
#RequestMapping(value = "/LoadCities.htm", method = RequestMethod.GET)
public #ResponseBody
List<City> getCityByCountryID(HttpServletRequest request, HttpServletResponse response)
throws Exception {
List<City> list=
icitys.getCitiesByCountry(Long.parseLong(request.getParameter("countryID")));
return list;
}
and in the JSP file I have the following City and country drop down menus:
<tr>
<td align="right">Country</td>
<td align="left">
<select id ="country" name="country" onchange="loadCity()">
<option value="0">--select--</option>
<c:forEach var="countrylst" items="${countriesList}">
<option value="${countrylst.id}">${countrylst.countryName}</option>
</c:forEach>
</select>
</td>
</tr>
<tr>
<td align="right">City</td>
<td align="left">
<select id="cityDD" name="cityDD">
<option value="0">--select--</option>
</select>
</td>
</tr>
Hope you got solution after changing $(country) to $('#country').
One more thing, you put dataType as "javascript" but avail data types are xml, json, script, or html.
Better try with html.
Good luck.
Should
var countryData="countryId="+$(country).val();
not be
var countryData="countryId="+$('#country').val();

Calling a jsp/html page using ajax in play 2.0

Can anyone guide me how can i call a jsp/html page using ajax in play framework?
I want to open a lightbox on click of a button and want to load that with a page containing data from database.
Currently i have just displayed the message using ajax. Below is the method inApplication.java
public static Result index()
{
return ok(index.render("Your new application is ready."));
}
My index.scala.html is:
#(products: List[Products])
#import helper._
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<h1>#products.size() product(s)</h1>
<table border=1>
<tr>
<td>Product Name</td>
<td>Quantity</td>
<td>Price</td>
</tr>
#for(product <- products) {
<tr>
<td>
#product.productname
</td>
<td>
#product.quantity
</td>
<td>
#product.price
</td>
<td id="items">
<input type="button" value="Add Product" name="#routes.Application.user(product.product_id)" id="but"/>
</td>
</tr>
}
</table>
<div class="result1" style="border: 1px solid black; padding: 5px;">not sent yet...</div>
<script type="text/javascript">
jQuery("#items a").click(
function () {
$.get(jQuery(this).attr("href"), function (data) {
$('.result').html(data);
});
return false;
}
)
</script>
You are on the good way.
Create a new action which will return only the html you need in your div (and not the complete html page).
public static Result detail(Integer productId)
{
Product product = .... (productId);
return ok(productDetail.render(product));
}
// with the route of course
productDetail.scala.html
#(product: Product)
My product #product.product_id is beautiful !
....
You must also add a jquery plugin to display your lightbox (there are a thousand...)
Your JsCode will be something like that:
$("#items a").click(function () {
$("#result").load($(this).attr("href"), function() {
displayPopup(); // code this
});
});
(Or maybe a totally different code if the plugin natively handle ajax...)
In resume, there is a lot of work to do, and many ways to do it.
Just try !

Categories