Implement pagination in JSP page in a Spring MVC and Hibernate application - spring

I am trying to implement pagination in my JSP page. I am using Spring MVC and Hibernate. The java code part is okay but I am having difficulties implementing it in my JSP page. I am using twitter bootstrap.
Here is what I did until now:
<div class="container">
<table class="table table-hover">
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
<c:forEach items="${employees}" var="emp">
<tr>
<td>${emp.firstName}</td>
<td>${emp.lastName}</td>
<td>${emp.Age}</td>
</tr>
</c:forEach>
</table>
<div class="pagination">
<ul>
<li class="disabled">First</li>
<li class="disabled">Prev</li>
<li class="active">1</li>
<li class="active">2</li>
<li class="active">3</li>
<li class="active">4</li>
<li class="active">5</li>
<li class="active">Next</li>
<li class="active">Last</li>
</ul>
</div>
</div>
This is the related code in my controller:
#RequestMapping(value = "/list", method = RequestMethod.GET)
public String getEmployees(ModelMap model) {
**//I believe I should get the page number from the JSP here but how?**
model.addAttribute("employees", this.employeeService.getEmployees(page));
return "listing";
}
This is the related code in my Service class:
public List<Employee> getEmployees(int page) {
return employeeDao.getEmployeeList(page);
}
This is the related code in my DAO class:
private static final int limitResultsPerPage = 3;
public List<Employee> getEmployeeList(int page) {
Query q = sessionFactory.getCurrentSession().createQuery(
"from Employee");
q.setFirstResult(page * limitResultsPerPage);
q.setMaxResults(limitResultsPerPage);
return (List<Employee>) q.list();
}
The page where I am displaying that table is list.jsp
Here are my assumptions of what I should do but dont know how (please correct me if I am taking the wrong way):
Modify my link that point to list.jsp in my menu, to list.jsp?page=0, so everytime the user clicks on the link, he will arrive in the first page.
When the user clicks one of the button, I need to pass the page number to my controller so I can manage to return the right "employees" with my query.
As you can see, the First and Previous buttons are deactivated as I am currently on the first page. So my question is, how should I handle the activation/deactivation of those buttons, as well as the Next and Last ones?
Also, how to "refresh" the numbers on the list? For example, if the user is at the page 20, I won't display buttons from 1 to 19?

To answer one of your questions at least:
You can pass the page number and other parameters from the JSP to your controller with the RequestParam annotation like this:
#RequestMapping(value = "/list", method = RequestMethod.GET)
public String getEmployees(#RequestParam(value = "page", required = false) Long page, ModelMap model) {
//now page is available.
model.addAttribute("employees", this.employeeService.getEmployees(page));
return "listing";
}
And your link will look something like this:
list/?page=1
Pagination is a fairly complicated process but here are a few ideas. You can use JSTL on the JSP page to implement the logic. For instance:
<c:if test="${page > 1}">
<li class="active">First</li>
</c:if>
I suggest that you do some calculations in the Action for the number of pages that you want to display. Say for instance that you always want to display ten links. On page 1, you will display pages 1...10, on page 7 you will display pages 2...12 and so on. In the action you can determine the starting page and the ending page to display.
int startpage = page - 5 > 0?page - 5:1;
int endpage = startpage + 10;
On the JSP page you can do a loop maybe:
<c:forEach begin="${startpage}" end="${endpage}" var="p">
${p}
</c:forEach>
and so on.

Vincent Ramdhanie solution is correct: thanks for that. Dukable: I used this code based on Vincent Ramdhanie's solution and it works really well: something like this should work in your code.
#RequestMapping(value = "/list", method = RequestMethod.GET)
public String getEmployees(#RequestParam(value = "page", required = false) Long page, ModelMap model) {
//now page is available.
int startpage = (int) (page - 5 > 0?page - 5:1);
int endpage = startpage + 10;
model.addAttribute("employees", this.employeeService.getEmployees(page));
model.addAttribute("startpage",startpage);
model.addAttribute("endpage",endpage);
return "listing";
}
And in your jsp:
<div class="pagination">
<ul>
<li><c:forEach begin="${startpage}" end="${endpage}" var="p">${p}</c:forEach></li>
</ul>
</div>
You can access to your jsp on this way:
http://localhost:8080/Project/list/?page=1

`<div class="box-tools pull-right">
<ul class="pagination pagination-sm inline">
<c:if test="${pageCtn gt 1}">
<li>
<c:choose>
<c:when test="${currentPage gt 1}">
«
</c:when>
<c:otherwise>
<a>«</a>
</c:otherwise>
</c:choose>
</li>
<li>${currentPage} to ${pageCtn}</li>
<li>
<c:choose>
<c:when test="${currentPage lt pageCtn}">
»
</c:when>
<c:otherwise>
<a>»</a>
</c:otherwise>
</c:choose>
</li>
</c:if>
</ul>
</div>`

Related

Redirect on controller advice expectionhandler with model attribute spring MVC

So i try to redirect from ExceptionHandler wit model attribute to the site where it was caused.
For example i have a controller method witch list the current items:
#AvailableInMenu
#RequestMapping(method = RequestMethod.GET)
public String list(Model model) {
model.addAttribute("Companys", iCompanyService.findAll().getData());
return "masters/crud/company/list";
}
An this is the template witch the method call:
<div th:if="${exception != null}" class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<strong>Warning!</strong><div th:text="${exception}" th:remove="tag" ></div>
</div>
<div class="ibox float-e-margins">
<div class="ibox-content">
<table id="table" class="table table-striped table-bordered nowrap">
<thead>
<tr>
<th th:text="#{app.maintanance.installversion}"></th>
</tr>
</thead>
<tbody>
<tr th:each="company : ${Companys}">
<td th:text="${company.installversion}"></td>
<td>
<a class="delete-button" th:attr="data-redir=#{/company/delete/{id}(id = ${company.id})}">
<i class="fa fa-pencil"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
This thymeleaf code generate a table with data and a delete link. Th entity wotch the user use has foreign key, and if the user want to delete it jpa thows a foreign key constraint witch i wrap into an error wrapper.
This is the controller method for the delete link:
#RequestMapping(value = {"/delete/{id}"}, method = RequestMethod.GET)
public String deleteCompany(Model model, #PathVariable("id") Long id) {
ErrorWrapper<Boolean> result = iCompanyService.deleteCompany(id);
if(result.hasError()){
if(result.getConstraint()){
throw new GlobalModelException(601L, "redirect:/company");
}
}
return "redirect:/company";
}
AS you can see if there was an error i throw general exception that i create, and a ControllerAdvice with ExpectonHandler where is catch my expection class. I want to add the exception to model and redirect back to the listing site, and show the bootstrap alert to the on the site.
This is the exceptionHandler from the ControllerAdvice
#ExceptionHandler(GlobalModelException.class)
public ModelAndView handlingException(GlobalModelException exception) {
ModelAndView model = new ModelAndView();
model.setViewName(exception.getUrl());
model.addObject("exception", exception);
return model;
}
The ModelAndView redirect me the correct place as it should be, but the exception is null after redirect. How can i call my listing site with the exception in the model with ControllerADvice. I have many other exceptions that i want to handle and a a lot of other controller where i need this.
Is there any way to do this?
You mush use RedirectAttributes/FlashAttribute.
http://viralpatel.net/blogs/spring-mvc-flash-attribute-example/
http://www.baeldung.com/spring-redirect-and-forward

ModelAttribute returns null values in controller in Spring MVC

Ok, its time to seek help; I am sending a (shopping) Cart ModelAttribute to my jsp, allowing the user to edit the quantity, when the Model is POST to the controller the fields are null except the editable (quantity) field. I have researched for days on similar issues but nothing is matching. I am using spring 3.1.
Here is my controller on the GET and POST:
#Controller
public class CartController {
#Autowired
private Cart cart;
#RequestMapping(value = "/cart", method = RequestMethod.GET)
public String showCart(Model model) {
logger.debug("CartController.showCart() Cart: {}", this.cart);
model.addAttribute(cart);
return "cart/cart";
}
and POST
#RequestMapping(value = "/cart", method = RequestMethod.POST, params = "update")
public String update(#ModelAttribute("cart") Cart cart, BindingResult result, Model model) {
logger.debug("CartController.update() Cart: {}", cart);
return "cart/cart";
}
my jsp:
<div class="container MainContent">
<form:form method="POST" modelAttribute="cart">
<fieldset>
<legend>Cart</legend>
<table class="table">
<thead>
<tr>
<th>Product Name</th>
<th>Quantity</th>
<th>Product Price</th>
</tr>
</thead>
<tbody>
<c:forEach items="${cart.cartDetails}" var="cartDetail" varStatus="status">
<tr>
<td>${cartDetail.product.name}</td>
<td><form:input path="cartDetails[${status.index}].quantity" size="1" /></td>
<td>${cartDetail.price}</td>
</c:forEach>
<tr>
<b><td colspan="2" align="right"><spring:message code="order.total" /></b>
</td>
<td>${cart.totalCartPrice}</td>
</tr>
</tbody>
</table>
</fieldset>
<div></div>
<button id="order" name="order">
<spring:message code="button.order" />
</button>
<button id="update" name="update">
<spring:message code="button.update" />
</button>
</form:form>
</div>
and the log results for cart before on GET:
CartController.showCart() Cart: Cart [cartDetails=[CartDetail
product=com.Product#c26440[name=My Name],
quantity=1]], totalCartPrice=10.00]
and after updating the quantity from 1 to 3 in the jsp and then POST to the controller:
CartController.update() Cart: Cart [cartDetails=[CartDetail
[product=null, quantity=3]], totalCartPrice=null]
I've read several similar post here and on the Spring forum and tried different suggested solutions with no luck. It seems like my edited quantity results are getting bound to the Object correctly but why aren’t the others?
Assuming you have all the necessary fields in your Form object;
You have to specify the form fields and fill the value with your data.
<td>${cartDetail.product.name}</td>
will only print the result to the screen. If you want to bind it to your form you have to put it in a spring form input such as:
<form:input path="productName" value="${cartDetail.product.name}"/>
If you don't want it to be editable then you can put it into a hidden field but in the end you'll have to put it in a form element in the jsp and have a corresponding field in your form POJO
Seems other fields aren't bound, try to bind for example product name
<td>${cartDetail.product.name}
<form:hidden path="cartDetails[${status.index}].product.name" value="${cartDetail.product.name}"/></td>
I once spent a lot of time investigating a similar issue. Finally I found the culprit inside a Binder's initialization method:
#InitBinder
void initBinder(final WebDataBinder binder) {
binder.setAllowedFields("name", ...);
}
This method sets a restriction on fields that are allowed for binding. And all the other fields are unbound, naturally resulting in null values.
The other possible reason: incorrect setters in a Bean annotated with #ModelAttribute. For example, Object setName(String name) instead of void setName(String).

Is't possible to get access to <ul> and <li> during submiting form

I have view with controller. I would like to know if it is possible to get access to ul and li? I don't want to do ajax call and pass these elements as parameters. Li elements are added on client side dynamically. this.Request.Form show me only 'name' variable without 'list'. Any advices?
<form action="#Url.Action("Filter")" method="POST">
<ul data-role="listview" data-inset="true" data-filter="false" name="list">
#foreach (var item in #Model.Items)
{
<li value="#item">#item</li>
}
</ul>
<input type="text" name="name"/>
<inpu type="submit" value="Filter"/>
</form>
and controller:
[HttpPost]
public ActionResult Filter(string name, List<string> list)
{
// working with list
return RedirectToAction("Index");
}
thanks
No,
It is not possible to access <ul> and <li> on post back.
BTW, the following code is generates <li> on server not on client
#foreach (var item in #Model.Items)
{
<li value="#item">#item</li>
}
If you wish to access Items (#item) on server, there are other ways to get those that do not require access to <ul> or <li>
For instance, you can emit a hidden (#Html.HiddenFor) element in each <li> in your loop.
You can try the following.
I'm not sure what your view model looks like, but it seems like a list of string values? So then it will look like this in your view model:
public class YourViewModel
{
public List<string> Items { get; set; }
}
In your view try the following:
<ul>
#for (int i = 0; i < Model.Items.Count(); i++)
{
<li>
#Html.DisplayFor(x => x.Items[i])
#Html.HiddenFor(x => x.Items[i])
</li>
}
</ul>
When you post then these items should still be in the list.
It might not be a perfect solution but it can guide you on the right track.
I hope this helps.

ViewBag does not show messege in view

I created 2 div's inside a view.
to display content inside that i have used partial view and to show errors i am using Viewbag and displayed it as follows:
<div id="tabs">
<ul>
<li>Publish Exhibition</li>
<li>Edit Existing Exhibition</li>
</ul>
<div id="tabs-1" style=" width:900px; height:400px;">
<font color="red">#ViewBag.msg1</font>
#{Html.RenderPartial("PubExhi", Model);}
</div>
<div id="tabs-2">
#{Html.RenderPartial("EditExhi");}
</div>
</div>
I'm calling this view as
ViewBag.msg1 = "record not updated!!!!";
modelList = setIndex();
return View("Index", modelList);
evry thing is working fine except the viewbag
it is not displaying any msgs
When i debugged it, i can see the viewbag containing appropriate value
but it is not displaying on the page
I also tried to display it from the partial view but not getting any message
Can any body help me
Use #Html.Raw(ViewBag.msg1) to display.....
It should work, i tried exactly similar thing and it is working for me -
<div id="tabs">
<ul>
<li>Tab 1</li>
<li>Tab 2</li>
</ul>
<div id="HWTab">
<font color="red">#ViewBag.msg</font>
#{Html.RenderPartial("_HardwareAssetView", Model.hardwareAssetVM);}
</div>
<div id="AdminTab">
#{Html.RenderPartial("_AdminAssetView", Model.adminAssetVM);}
</div>
you need to assign it to the view you are sending in your server method: let's say my viewresult is Details, but you are sending view DetailingList, then you need to assign this view's viewbag the message you want:
var partialViewRes = new PartialViewResult();
partialViewRes.ViewName = "DetailingList";
partialViewRes.ViewData.Model = list;
partialViewRes.ViewBag.ErrorMessage = "Error on loading";
Hope this helps someone.

Request.Forms.Keys.Count = 0 on Postback

I have the following HTML on my displayed form
<fieldset>
<legend>Edit User Roles</legend>
<ul>
<% foreach (string role in (string[]) ViewData["roles"]){ %>
<li>
<div id="Div4" class="grid_6">
<div id="Div5" class="grid_2 alpha" style="font-weight: bold;">
<%= Html.CheckBox("role." + role, Roles.IsUserInRole(Model.UserName, role))%>
</div>
<div id="Div6" class="grid_3 omega" style="font-family: Verdana; font-size: 10pt;">
<label for="role.<%: role %>">
<%: role %></label><br />
</div>
</div>
</li>
<% } %>
</ul>
</fieldset>
I have the following code in my Controller
[HttpPost]
public ActionResult EditUser( string id, bool approved )
{
int i = Request.Form.Keys.Count
foreach (string key in Request.Form.Keys)
{
if (key.StartsWith( "role." ))
{
// Do something
}
}
MembershipUser membershipUser = Membership.GetUser( id );
return View( membershipUser );
}
If I break the code and explore, I find that the Request.Form.Keys.Count = 0, although there should be at least 4 keys created with "role." as a prefix from four checkboxes displayed on the form.
What am I not understanding here?
Request.Form.Keys.Count = 0 could have two possible explanations:
No value was sent in the POST body
You used some special content type such as for example application/json instead of application/x-www-form-urlencoded (could happen if you play with AJAX)
I would recommend you using FireBug to see exactly what's contained in the POST request and if there are any values. You haven't shown the form definition neither how you are submitting it. If you are POSTing with AJAX maybe there's where the problem lies.
Here's an example of how a valid request might look like in FireBug:

Resources