Dynamic table in JSP and Spring MVC - spring-mvc

I am writing an application using Spring MVC and Hibernate. In one of my application pages, the JSP page consists of dynamically generated tables based on the criteria specified by the end-user. For example, the end-user enters the "number of employees" on the page and upon clicking submit, the next page shows all the companies that have a number of employees equal to or greater than the value entered by the end-user. For each company, a separate / individual table is generated, header of the table shows the name of the company from database (This part is working completely fine). Now in the table for the company itself, I want to display data for that company only and likewise, every table header will display the name of the company and the data for that company only. Any ideas of how can I display the data for company in the table. Below is my code
Controller
Int numberOfemployees // This value is entered by the end user
List<Company> companies = companyService.listAllCompany(numberOfEmployees );
ModelAndView companiesResults = new ModelAndView("companies-result");
CompanyForm companyForm = new CompanyForm();
companyForm.setCompanies(companies);
companiesResults.addObject("company", companies);
for (Company company : companies) {
int company_id = company.getCompany_id(); //Get id of the company to get its attributes/data from database
List<CompanyAttribute> companyAttributes =companyService.listCompanyAttributes(company_id);
}
companyForm.setCompanyAttributes(companyAttributes);
companiesResult.addObject("companyForm", companyForm);
companiesResult.addObject("companyAttributte", companyAttributes);
}
Below is my JSP
<c:forEach items="${companyForm.companies}" var="company" varStatus="status">
<h6>${company.company_name}</h6>
<div class="table-responsive">
<table>
<thead>
<tr>
<th>Company portfolio</th>
<th>Company points</th>
</tr>
</thead>
<tbody>
<c:forEach items="${companyForm.companyAttributes}" var="companyAttribute" varStatus="status">
<tr>
<td>${companyAttribute.portfolio}</td>
<td>${companyAttribute.points}</td>
</tr>
</c:forEach>
</tbody>
</table>
</c:forEach>
I will appreciate any ideas on how can I display data for each company in its table. My approach is showing me empty table for every company. Should I use some kind of scripplet in JSP page or is there any other approach. I am new to JSP and Spring MVC, any ideas will be appreciated.

I had a similar problem a few years ago and solved it that way:
// In my controller
mav.addObject("order", order);
// In my jsp
<c:forEach items="${order.articles}" var="article">
...
</c:forEach>
This is not working. But then I tried this
// In my controller
mav.addObject("articles", order.getOrderArticles());
// In my jsp
<c:forEach items="${articles}" var="article">
it works as expected. As you can see I added the list of articles as another object in my model. And then it is possible to iterate over this object in the jsp.

Related

How to perform a nested Thymeleaf loop to create a table containing fields from two JPA table classes

I'm trying to create a web page using a thymeleaf template to present a table of Orders with a field that provided a list of products associated with a specific order.
My controller class:
#Controller
public class WebPage {
#Autowired
private OrderRepository orderRepository;
#Autowired
private ProductRepository productRepository;
#RequestMapping("/test")
public String index(Model model) {
model.addAttribute("ordertable", orderRepository.findAll());
model.addAttribute("producttable", productRepository.findAll());
return "tablepage";
}
}
Relevant part of thymeleaf template:
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>stuff</th>
<th>Stuuff</th>
<th>stuff</th>
<th>products</th>
</tr>
</thead>
<tbody>
<tr th:each="ordertbl: ${ordertable}">
<td th:text="${ordertbl.stuffId}"/>
<td th:text="${ordertbl.stuffname}"/>
<td th:text="${ordertbl.stuffname}"/>
<td th:text="${ordertbl.stuff}"/>
<td>
<span th:each="producttbl: ${producttable}"><span th:text="${ordertbl.products}"/></span>
</td>
</tr>
</tbody>
</table>
What this does is creates a table of orders but in the final field, it lists all the products contained in the order several times depending how many products are in the product table.
How would I change this so that the the order field lists the products belonging to each row just once. I am aware that this is most likely a nested for loop error, or a problem with my use of findall() method but I'm not sure how to fix it.
I would prefer to use the nested product table rather than fetching the products from the order jpa entity class.
Thanks.
If you're trying to display products of each order, then this line is wrong:
<span th:each="producttbl: ${producttable}"> <span th:text="${ordertbl.products}" /> </span>
You're iterating against the producttable list you have in your model, not of the current ordertbl's products in the loop. It should be
<span th:each="producttbl: ${ordertbl.products}"> <span th:text="${producttbl}" /></span>

Pass loop variable from Freemarker template to Spring controller

I am listing objects in a table in my view. I want to be able to edit an object using a button in the table.
<#list products as product>
<tr>
<td>${product.productName}</td>
<td>${product.price}</td>
<td>${product.quantity}</td>
<td>
<form name="product" method="post" action="/product/edit">
<input type="submit" name="submit" value="Edit this product"/>
</form>
</td>
</tr>
</#list>
The object then should be passed to a controller method:
#RequestMapping(value="/edit", method = RequestMethod.POST)
public ModelAndView edit(#ModelAttribute("product") Product product){
ModelAndView mav = new ModelAndView("product/edit");
mav.addObject("product", product);
return mav;
}
However, the product obtained by the edit method is null. How do I fix this? I tried to bind the product inside form using the code below, but that did not work either.
<form name="product" method="post" action="/product/edit">
<#spring.bind "product" />
<input type="hidden" name="${spring.status.expression}" value="${spring.status.value}"/>
<input type="submit" name="submit" value="Edit this product"/>
</form>
I want to use the POST method.
I would like to suggest a different approach. If I'm not mistaken you just want to pick an object for later editing - you don't really edit it in that very view.
If so, all you have to do is to pass an identifier of your object to your controller, but not the selected object itself.
If not, you should give us the hole story and provide the rest of the view as well.
Assuming I'm right the next question is why you need to use a form submission at all. Passing an id is best done by links - either as parameter or, if you follow REST-style, as part of the URI itself:
<!-- Link parameter -->
<#list products as product>
<tr>
<td>${product.productName}</td>
<td>${product.price}</td>
<td>${product.quantity}</td>
<td>
Edit ${product.productName}
</td>
</tr>
</#list>
<!-- REST-style -->
...
Edit ${product.productName}
...
productName isn't a good id of course. If products is a list (meaning, java.util.List) the index of the list is handy. Even in a HashMap or Set I'd create a unique id instead of using the product name.
Now that you can identify your object, select it in the backing code for later editing, but not in the view.
You'll find loads of examples of how to get link parameters in a controller. So, no need to go into detail here.
If however you insist on using a form and a POST-method then do it like this:
<form method="post" action="/product/edit">
<#list products as product>
<tr>
<td>${product.productName}</td>
<td>${product.price}</td>
<td>${product.quantity}</td>
<td>
<button value="${product.productName}" name="product" type="submit">Edit ${product.productName}</button>
</td>
</tr>
</#list>
</form>
Note that this won't work for older IE browsers (below Ver. 10), because they don't return the value, but everything that is inside the button tag.
Hidden inputs and a single submit button won't help at all, because all inputs are submitted and using different forms is not the way either.

How to get list of checked checkbox from jsp form

I am trying to assign some subjects to a course in below code. I am using springmvc framework.
The webpage looks like this -
http://oi59.tinypic.com/28qrpeh.jpg
What i want that if someone check some subjects in webpage i should able to get the list of those chosen subjects. I tried to search for the example but not able to find any. If some one can help me with it would me really appriciated.
<form:form commandName="course">
<c:forEach items="${subjectList}" var="subject">
<tr>
<td><input type="checkbox" name="subject2" value="${subject.id}" /> ${subject.name }</td>
</tr>
</c:forEach>
</form:form>
You can do that with getParameterValues("subject2") which will return an array of String.
then you loop through them, for instance
String[] Answers = request.getParameterValues("subject2");
PrintWriter out=response.getWriter();
for(int i =0; i<Answers.length; i++){
out.print(Answers[i]+ "<br>");
}

Why is my statically typed partial view trying to render an unintended model type?

I have a partial view, in my ASP.NET MVC4 web app. It's just a partial view designed to display a table, given a collection of entities. It looks like this:
#model ICollection<Portal.Models.Matter>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Name</th>
<th>Last Accessed</th>
<th>Client</th>
</tr>
</thead>
<tbody>
#if (Model.Count > 0)
{
#Html.DisplayForModel()
}
else
{
<tr>
<td colspan="3" class="text-muted text-centered">There are no Matters to display.</td>
</tr>
}
</tbody>
</table>
I have a DisplayTemplate for Matter that is statically typed to the single Matter entity, and it handles rendering of each table row.
For some reason, when this partial is rendered, instead of using the Matter DisplayTemplate it just shows the following:
System.Collections.Generic.List`1[Portal.Models.Account]System.Collections.Generic.List`1[Portal.Models.Account]
Now, this partial is not even bound to a collection of Account entities. It's bound to a collection of Matter entities. So, why is #Html.DisplayForModel() trying to display for a collection of Accounts? At run time, using a debugger, I can see the Model is in fact a collection of Matter entities, not Account.
I render this partial using the following code:
#Html.Partial("~/Views/Matter/_Table.cshtml", Model.Client.Matters, new ViewDataDictionary())
I found a work around, or maybe a solution, not sure. Anyway, instead of using DisplayForModel on an ICollection, I iterate over the collection and use DisplayFor on each element.
For example ...
#model ICollection<Foo>
for (var item in Model)
{
#Html.DisplayFor(m => item)
}
I guess nothing is forcing you to use a property off of m in DisplayFor.

asp.net razor Model Binding Dynamic List in Form submission

I am trying to create an order form for input.
I need the user to be able to add multiple line items then update. I was trying to
use the shopping cart class (where user creates a cart item and adds a
list item, multiple lines can be added to the list item).
I didn't get through with that. I am using asp.net razor am using
webmatrix to build site. Webmatrix is saying that it doesnt recognise Cart().
#{
if (Session["cart"] == null)
{
Session["cart"] = new Cart();
}
Cart cart = (Cart)Session["cart"];
}
<table id="cartTable">
<tr>
<th class="product">Product</th>
<th class="size">Size</th>
<th class="price">Price</th>
</tr>
#foreach (var item in cart.Items)
{
<tr>
<td class="product">#item.ProductID</td>
<td class="size">#item.Size</td>
<td class="price">£#item.Price</td>
</tr>
}
</table>
Is there a better way to do this? All help is greatly appreciated
There IS a way to bind dynamic list elements
#foreach (i=0; i< cart.Items.count; i++)
{
<tr>
<td class="product"> <input type="hidden" name="cart.item[#i].ProductID"> </td>
<td class="size"> <input type="text" name="cart.item[#i].Size"> </td>
<td class="price">£ <input type="text" name="cart.item[#i].Price"> </td>
</tr>
}
Webmatrix is saying that it doesnt recognise Cart()
I strongly recommend you place your Models in the Models folder and make them part of the Models namespace. Then they should be available automatically. Otherwise, you may have to reference cart by it's complete reference path (if it is not in your Models folder). example
Datalayer.Entities.Cart cart = (Datalayer.Entities.Cart)Session["cart"];
Final Note:
You are not passing your Cart as a Model to your View
example
#model {Project}.Entities.Cart
This is a better practice using the MVC 3 framework. You would have discovered whatever reference problem earlier and would have the option to use tightly bound Helpers
I recommend using the Visual Studio 2012 Express over WebMatrix for MVC development. Furthermore, I would also suggest using jQuery (javascript) if you wish to let users add line items on the fly via the same page. I can share an example with you if you like.
One more note: You tagged this with both MVC and WebForms, which are two very different platforms.
Edit:
I think Dave A's solution may be better, but to do this with jQuery:
1 Put your add button and hidden div in a form
<form action="/MyController/MyAction" method="post" id="addListItemForm">
<button id="addListItemButton">Add List Item</button>
<div style="hidden">
<input type="text" name="product" id="product" />
<button id="addButton">Add</button>
</div>
<input type="submit" text="Submit" />
</form>
2 Show the form fields on button click
$('#addListItemButton').click(function(){
$('#addListItemForm div').show();
});
3 Add hidden field on add button click
$('#addButton').click(function(){
var product = $('#addListItemForm #product').val();
$("input").attr({
name : "productListItems[]",
type : "hidden",
value : product
}).after('#addListItemForm');
});
4 When the form submits, you will have various product names in the productListItems array passed via POST method.
Note: You'll have to play with this a little bit, but it would be a good learning exercise... I am not exactly sure what you are trying to do, but this is my best guess.

Resources