I have an ArrayList and i am trying to display it in a table
.....
ArrayList rows = ....
.....
<table cellspacing="1" cellpadding="4" border="3">
<tr>
<TH>
Heading1
</TH>
<TH>
Heading2
</TH>
<TH>
Heading3
</TH>
<TH>
Heading4
</TH>
<TH>
Heading5
</TH>
<TH>
Heading6
</TH>
<TH>
Heading7
</TH>
</tr>
<tr>
<% for (int i = 0; i < rows.size(); i++) {
for (int j = 0; j < 7; j++) {
%>
<td>
<center>
<% out.println( ????? ); %>
</center>
</td>
<% } %>
</tr>
<% } %>
</table>
but i am having trouble displaying the correct data.
Well for one thing, I suspect that your outer loop should start above the <tr> tag.
Other than that, an ArrayList is a one-dimensional structure (not surprisingly, since it's a list). Trying to display this data in a table implies it's two dimensional, but without generics you've given no information as to what's contained within the list.
I'd approach this something like this:
/* header rows */
<% for (int i = 0; i < rows.size(); i++) {
Object rowObj = rows.get(i);
%>
<tr>
<% for (int j = 0; j < 7; j++) {
// This RHS made up due to not knowing the class of objects
// in your map, use something equivalent
Object cell = rowObj.getEntry(j);
%>
<td>
<center>
<%=cell.toString()%>
</center>
</td>
<% } %>
</tr>
<% } %>
You should not use scriptlets for this. Use JSTL/EL for this. Shortly back I've posted an example, you can find here: Places where JavaBeans are used?
It's a perfect scenario for using JSP taglibs. There is a huge list of available tablibs over at jsptags.com That way the HTML will be very readable but you'll have your dynamic table.
As others have pointed out you would want to use tags rather than generate a table yourself using scriptlets. The benefits are more than I care to list here. I would recommend looking at the Display tag library. It makes it trivially easy to generate a table from any Collection.
<display:table name="rows">
<display:column property="id" title="ID" />
<display:column property="name" />
<display:column property="email" />
<display:column property="status" />
<display:column property="description" title="Comments"/>
</display:table>
Of course each column would refer to a property of the objects that you have in your ArrayList.
You may use core JSTL library (download it from http://jakarta.apache.org/site/downloads/downloads_taglibs.html).
Include jstl.jar and standard.jar libraries from this distribution into you class path. Then place directive <%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> on top of your jsp-file. And use construction like this:
...
<br/>
<table><br/>
<c:forEach items="${rows}" var="row"><br/>
<tr><br/>
<c:forEach items="${row}" var="column"><br/>
<td><br/>
<c:out value="${column}"/><br/>
</td><br/>
</c:forEach><br/>
</tr><br/>
</c:forEach><br/>
</table><br/>
...
Related
JSoup here. I have the following HTML I'm trying to parse:
<html><head>
<title>My Soup Materials</title>
<!--mstheme--><link rel="stylesheet" type="text/css" href="../../_themes/ice/ice1011.css"><meta name="Microsoft Theme" content="ice 1011, default">
</head>
<body><center><table width="92%"><tbody>
<tr>
<td><h2>My Soup Materials</h2>
<table width="100%%" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td align="left"><b>Origin:</b> Belgium</td>
<td align="left"><b>Count:</b> 2 foos</td>
</tr>
<tr>
<td align="left"><b>Supplier:</b> </td>
<td align="left"><b>Must Burninate:</b> Yes</td>
</tr>
<tr>
<td align="left"><b>Type:</b> Fizzbuzz</td>
<td align="left"><b>Add Afterwards:</b> No</td>
</tr>
</tbody>
</table>
<br>
<b><u>Notes</b></u><br>Drink more ovaltine</td>
</tr>
</tbody>
</table>
</center></body>
</html>
Unfortunately its actually slightly malformed (missing some closing tags, opening and closing tags on <b> and <u> are out of order, etc.) but I'm hoping JSoup can handle that. I don't have control over the HTML.
I have the following Java model/POJO:
#Data // lombok; adds ctors, getters, setters, etc.
public class Material {
private String name;
private String origin;
private String count;
private String supplier;
private Boolean burninate;
private String type;
private Boolean addAfterwards;
}
I am trying to get JSoup to parse this HTML and provide a Material instance from that parsing.
To grab the data inside the <table> I'm pretty close:
Material material = new Material();
Elements rows = document.select("table").select("tr");
for (Element row : rows) {
// row 1: origin & count
Elements cols = row.select("td");
for (Element col : cols) {
material.setOrigin(???);
material.setCount(???);
}
}
So I'm able to get each <tr>, and for each <tr> get all of its <td> cols. But where I'm hung up is:
<td align="left"><b>Origin:</b> Belgium</td>
So the col.text() for the first <td> would be <b>Origin:</b> Belgium. How do I tell JSoup that I only want the "Belgium"?
I think you're looking for tdNode.ownText(). There's also simply text(), but as the docs state this combines all text nodes of the node and all its children and normalizes them. In other words, tdNode.text() gives you the string "Origin: Belgium". tdNode.ownText() gives you just "Belgium" and tdNode.child(0).ownText() gets you just "Origin:".
You can also use wholeText(), which is non-normalized, but I think you want the normalization here (that primarily involves getting rid of whitespace).
I would like to know why I am not able to get values from an outer hashtable using the keys in jstl, the keys are integer values, the values are inner hashtables and I am working on some legacy code hence the reason for the Hashtables, which are returned from a stored procedure call in this form.
Oddly in the inner hashtable as I process it in my forEach loop I am able to get those values out... ${data['NAME']} actually does work.
I am able to loop over the entire outer hashtable using JSTL forEach loop and its ok but if I try to get a value like ${missing_ciphers[1]} or even ${missing_ciphers['1']} then nothing is returned.
The hashtable when printed looks like this:
{4={SOURCE=D, NAME=D}, 3={SOURCE=C, NAME=C}, 2={SOURCE=B, NAME=B}, 1={SOURCE=A, NAME=A}}
I am able to loop over it ok using the following code but the list is not in the order I want it to be in so I wanted to use the loop counter to get objects out by their key but this doesnt seem to return anything (the inline styles will be moved into a css file once I have this working as I want...):
<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="data" value="${ciphers.value}">
</c:set>
<tr style="border-left: none; border-right: none;" class="${cipher_loop.index % 2 == 0 ? 'even' : 'odd'}">
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
Can anyone help me understand what is happening here and why I am not able to get a value out using the ${missing_ciphers[1]} type syntax?
I should add that the following code does print the inner hashtable into the tomcat console:
<% System.out.println("val: " + ((Hashtable)request.getAttribute("missing_ciphers")).get(1)); %>
I have even tried the following just to see if it was down to the type of the key this still doesnt get from the outer hashtable:
<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="counter" value="${cipher_loop.index + 1}" />
<fmt:parseNumber var="fmt_counter" integerOnly="true" type="number" value="${counter}" />
<c:out value="${fmt_counter}" />
<c:set var="data" value="${missing_ciphers[fmt_counter]}"></c:set>
<tr style="border-left: none; border-right: none;" class="${cipher_loop.index % 2 == 0 ? 'even' : 'odd'}">
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
Thanks
You should be using variable name assigned to varStatus - 'cipher_loop' and not varStatus itself.
Also you should use the index property or the count property to get the current index. (index starts at 0 and count at 1 by default)
${missing_ciphers[varStatus]}
should be
${missing_ciphers[cipher_loop.count]}
Edit
What is the type of your key in your outer hastable? Integer?
The type of varStatus.index (or counter) is long and you will have to explicitly set it as integer to use it as a key of your outer table
The following code works for me
<jsp:directive.page import="java.util.*"/>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
Hashtable h = new Hashtable();
Hashtable h1 = new Hashtable();h1.put("SOURCE","D");h1.put("NAME","D");
Hashtable h2 = new Hashtable();h2.put("SOURCE","C");h2.put("NAME","C");
Hashtable h3 = new Hashtable();h3.put("SOURCE","B");h3.put("NAME","B");
Hashtable h4 = new Hashtable();h4.put("SOURCE","A");h4.put("NAME","A");
h.put(4,h1);h.put(3,h2);h.put(2,h3);h.put(1,h1);
request.setAttribute("missing_ciphers",h);
%>
<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="counter" value="${cipher_loop.index + 1}" />
<c:out value = "${counter}"/>
<c:set var = 'counter' value = '<%=new Integer(pageContext.findAttribute("counter").toString())%>'/>
<c:set var="data" value="${missing_ciphers[counter]}"></c:set>
<tr>
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
OTOH, if the keys in your table is of type long, then you can use the varstatus.index property directly
<jsp:directive.page import="java.util.*"/>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
Hashtable h = new Hashtable();
Hashtable h1 = new Hashtable();h1.put("SOURCE","D");h1.put("NAME","D");
Hashtable h2 = new Hashtable();h2.put("SOURCE","C");h2.put("NAME","C");
Hashtable h3 = new Hashtable();h3.put("SOURCE","B");h3.put("NAME","B");
Hashtable h4 = new Hashtable();h4.put("SOURCE","A");h4.put("NAME","A");
h.put(new Long(4),h1);h.put(new Long(3),h2);h.put(new Long(2),h3);h.put(new Long(1),h1);
request.setAttribute("missing_ciphers",h);
%>
test
<<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="counter" value="${cipher_loop.index + 1}" />
<c:set var="data" value="${missing_ciphers[counter]}"></c:set>
${data}
<tr>
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
My requirement is as below.
Whenever user clicks on Additem button One new row should be added in the table.(Table Name : additionalInfoTable).
The must have three cells.
First two cells must have Text field.
Second cell must have dropdown with a list of Values.
For this I have written code in Javascript as below. But When I generate dropdown values from Java ArrayList, Java snippet is not running inside InnerHTML.
function addAdditionalRow() {
var table = document.getElementById("additionalInfoTable");
var row = table.insertRow(-1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
cell1.innerHTML = '<input type="text" size="15" name="additionalCost" />';
cell2.innerHTML = '<input type="text" size="15" name="totalCost" />';
cell3.innerHTML = '<select name="recoveryType">'+
'<option>--Select Recovery Type--</option>';
<% for(String recType: details.getRecoveryTypeList()) { %>
var recType = '<%=recType%>';
cell3.innerHTML = '<option value="'+recType+'">'+recType%+'</option>';
<%}%>
cell3.innerHTML = '</select>';
cell4.innerHTML = '<input type="button" value="Delete" onclick="deleteRow(this)"/>';
}
My JSP code for the table is below.
<table border ="1" width="100%" id="additionalInfoTable">
<thead>
<tr>
<td align="center" ><b>Additional Cost $</b></td>
<td align="center" ><b>Total Cost</b></td>
<td align="center" ><b>Recovery Type</b></td>
<td align="center" ><b>Delete</b></td></tr>
</tr>
</thead>
<tbody id="addBillbackdata">
<tr>
<td align="center">
<input type="text" size="15" name="additionalCost" />
</td>
<td align="center">
<input type="text" size="15" name="totalCost" />
</td>
<select name="recoveryType">
<option>--Select Recovery Type--</option>
<% for(String recType: details.getRecoveryTypeList()) { %>
<option value="<%=recType%>"><%=recType%></option>
<%}%>
</select>
</td>
<td align="center">
<input type="button" value="Delete" onclick="deleteRow(this)"/>
</td>
</tr>
</tbody>
</table>
Please help me to get Java ArrayList values inside innerHTML of javascript
Your javascript modifies the HTML in the browser. JSP code is compiled serverside before it is being delivered to the browser. It is not possible to use JSP code in javascript, because the browser has no way of interpreting it. You have to either
create the desired html with jsp, hide it (e.g. with display:none), and attach it dynamically with javascript
create a global javascript variable in jsp within a <script>-Tag and reference it from your button callback
create a different jsp or servlet to deliver the data and use AJAX to request it
I have a JSP page where I am showing all the products that fall under a specific category. The problem is that all of them either end up showing either vertically or horizontally based on whether I loop my "td" or "tr". I want to show them in grid where 3 products are in row 1, another 3 in row 2 and so on. Any idea on how this can be achieved?
ProductController.java
List<Product> productsLst = MasterDao.getAllProductsByCategory(new Integer(categoryId));
products.jsp
<table>
<tr>
<%
for (Product p : productsLst) {
%>
<td align="center">
<img src="../images/<%= p.getImage()%>" class="product-grid-img"/>
<br/><div id="product-name"><%= p.getName()%></div>
<br/><div id="money">$ <%= p.getListPrice()%></div>
</td>
<%
}
%>
</tr>
</table>
Just use a counter, if you got 3 products close the tr and open a new tr
Using Guava's Lists.partition() method:
List<List<Product>> rows = Lists.partition(productList);
page.setAttribute("rows", rows);
...
<c:forEach var="row" items="rows">
<tr>
<c:forEach var="product" items="row">
<td> ... details of the product ... </td>
</c:forEach>
</tr>
</c:forEach>
Already answer in this thread
<table>
<s:iterator value="productList" status="status">
<s:if test="#status.index %4 == 0">
<tr>
</s:if>
<td>
<img src="../product/image?imageID=<s:property value="productID"/>&type=thumbnail" />
</td>
<s:if test="#status.index %4 == 0">
</tr>
</s:if>
</s:iterator>
<table>
I'm trying to use a table to display some images, I'm allowed 3 images per row but I'm not sure how to end the table row when I have a row with less then 3 images. See the snippet below for what I've been trying.
Using a ul I would not have to worry about it but I'm directed to use a table. How can I make sure the last row is properly terminated ? I'm newer to jstl.
Thanks,
<% int endTRFlag = 0; %>
<table width="100%">
<tr>
<core:forEach var="imageURL" items="${actionBean.imageURLs}" varStatus="rowCounter">
<td align="center" valign="middle">
<div class="item">
<img src="${imageURL}" alt="Photo 1" class="img" />
</div>
</td>
<% endTRFlag = 1; %>
<core:if test="${ (rowCounter.count % 3 == 0) }">
</tr>
<tr>
<% endTRFlag = 0; %>
</core:if>
<core:if test="${ (rowCounter.count % 3 != 0) && (endTRFlag == 0)}">
</tr>
</core:if>
</core:forEach>
In the code below, I use .index instead of .count because it is 0-based, and so will work better for modulus (0/3, 3/3, etc.). .last is true if the current element is the last element in the list. This solution does cause validation errors in Eclipse (at least Ganymede), which is annoying.
<c:forEach var="imageURL" items="${actionBean.imageURLs}" varStatus="rowCounter">
<c:if test="${rowCounter.index mod 3 eq 0}">
<tr>
</c:if>
<td>stuff</td>
<c:if test="${(rowCounter.index+1) mod 3 eq 0 or rowCounter.last}">
</tr>
</c:if>
</c:forEach>
Just put the </tr> after the loop.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<c:set var="imageCnt" value="${fn:length(actionBean.imageURLs)}"/>
<table width="100%">
<tr>
<c:forEach var="imageURL" items="${actionBean.imageURLs}"
varStatus="rowCounter">
<td align="center" valign="middle">
<span class="item">
<img src="${imageURL}" alt="Photo 1" class="img" />
</span>
</td>
</c:forEach>
<c:forEach begin="${imageCnt}" end="2">
<td/>
</c:forEach>
</tr>
</table>