Thymeleaf: th:each for two table rows? - java

How can I, inside a th:each loop create a group of two rows instead of just one?
I know I can do:
<tr th:each="obj: ${listOfObjects}">
<td>a column with data: ${obj.id}</td>
</tr>
However, I want two <tr> elements to be created, as I would do with JSTL:
<c:forEach items="${listOfObjects}" var="obj">
<tr>
<td>${obj.id}</td>
</tr>
<tr>
<td>${obj.name}</td>
</tr>
</c:forEach>
Is there a way to achieve that with Thymeleaf?

You could use a th:block element for grouping the rows together and repeat them:
<th:block th:each="obj: ${listOfObjects}">
<tr>
<td th:text="${obj.id}"></td>
</tr>
<tr>
<td th:text="${obj.name}"></td>
</tr>
</th:block>
You can read more about th:block here

Related

How to display something on Thymeleaf table if not null

I have a table:
<table>
<thead>
<tr>
<th>Header1</th>
<th>Header2</th>
</tr>
</thead>
<tbody>
<div th:if="${param1 != null}">
<td class="dripicons-checkmark"></td>
</div>
<div th:if="${param2 != null}">
<td class="dripicons-checkmark"></td>
</div>
</tbody>
</table>
param1 and param2 are coming from my controller:
model.addAttribute("param1", param1)
model.addAttribute("param2", param2)
...and they can be null or contain some info. I'm trying to show a checkmark under correct header. If param1 is not null, I want to show the checkmark under Header1 and if param2 is not null, I want to show the checkmark under Header2 and so on. The code above shows the checkmark always under Header1, if either one of the params are not null. How can I put the icon under a correct header?
If either one of your params is null, then you will only be creating one <td> cell in the <tr> row. Your table always needs two cells to match the two headings you have.
There are various ways around this. The following is one way, which I think is reasonably concise:
<tbody>
<td th:class="${param1} != null ? 'dripicons-checkmark' : null"></td>
<td th:class="${param2} != null ? 'dripicons-checkmark' : null"></td>
</tbody>
In this example, we always have two row cells.
The "if" condition is inside a th:class attribute, so there is no need for any surrounding <div> elements.
The HTML generated by this is as follows, when the first value is null, but the second value is not null:
<table>
<thead>
<tr>
<th>Header1</th>
<th>Header2</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td class="dripicons-checkmark"></td>
</tr>
</tbody>
</table>

How to click a button from a table where all classes have the same name

<tbody>
<tr class="b">
<td class="t_l">betmatrix</td>
<td class="t_l">
<td class="t_r">dsdfsf</td>
<td class="t_r">NONE</td>
<td class="t_r">ALL</td>
<td class="t_r">NONE</td>
<td class="t_r">ALL</td>
<td class="t_r">ALL</td>
<td class="t_r">NONE</td>
<td class="t_r">ALL</td>
<td class="t_r">Not required</td>
<td class="t_r">1.11</td>
<td class="t_r">All User</td>
<td class="t_r">0.00</td>
<td class="t_r">2014-09-05</td>
<td class="t_r">2014-09-15</td>
<td class="t_r">2014-09-05</td>
<td class="t_r">1-admin</td>
<td class="t_r">
<td class="t_r">0.00</td>
<td class="t_r">0.00</td>
<td class="t_r">
<td class="t_r">
<a onclick="showBonusModificationLogs(53599)" href="#">History</a>
</td>
</tr>
<tr class="a">
<tr class="b">
<tr class="a">
</tbody>
This is the table structure that I have, and there is no way I can search only for specific items in the table.
How can I find an element in a row and then click on the button at the end of the row if it is found?
In this example I would need to search for the word: dsdfsf
It was easier for other tables because the classnames were different. But the same method will not work here.
As #alecxe pointed out, you can use XPath. There are probably hundred different ways of doing this. But to match your requirements I would use: //tr[td[text()='dsdfsf']]/td/a. This says: any row that has a column with the text 'dsdfsf', locate a column with an anchor tag.
You can find element By.xpath:
WebElement element = driver.findElement(By.xpath('//table//tr[td[#class="t_r"] and text() = "dsdfsf"]/td[last()]'));
element.click();
The xpath would search in every tr inside the table for the td with class t_r and text dsdfsf, then would get the last td inside the row.

How to retrieve the data of <s:radio> within <s:iterator> tag into Struts2's action

I need to do something in webpage like this :
a bunch of rows that display questions and choices , the choices are made up of radio buttions.
I don't konw how to get these radio button's data into my java code.
This is my jsp code:
<s:iterator value="questionsList" status="status" var="questionsList">
<tr>
<td><s:property value="title"/></td>
</tr>
<tr>
<td>
<s:radio list="{'A','B','C','D'}" name="[%{#status.index}]answer" theme="simple"/>
</td>
</tr>
</s:iterator>
I've tried
private List answer = new ArrayList();
answer = (List)request.getAttribute("[%{#status.index}]answer");
but it doesn't work.
If you have other means to do this please tell me, thank you!
You can provide indexed property names for the lists you want to get in Java
<s:iterator value="questionsList" status="status">
<tr>
<td><s:property value="title"/></td>
</tr>
<tr>
<td>
<s:radio list="{'A','B','C','D'}" name="questionsList[%{#status.index}].answer" theme="simple"/>
</td>
</tr>
</s:iterator>
Voila! Your question list will be populated with indexes provided by status.index variable.

add a serial number while performing iteration in thymeleaf

I have a senario in which i must perform iteration on a list and display result as a grid.Also include serial number in it. Now what I did for serial number is given below
<div th:with="i=0">
<tr th:each="mydate:${data.Listdata}" >
<div th:with="i=${i+1}">
<td th:text="${i}">
</div>
//other codes
</tr>
</div>
but only 1 appears in all serial number.Can anyone help me with this?
You can use the index of the iteration status:
<tr th:each="item,iterator : ${items}">
<td th:text="${iterator.index}"></td>
</tr>
You can use the iterationStatus to begin with 1 instead of 0.
<tr th:each="item,iterationStatus : ${items}">
<td th:text=${iterationStatus.count}></td>
</tr>
This gives the table Sno. Starting with 1.
To get the index:
<tr th:each="item: ${items}">
<td th:text="${iterator.indexOf(item)}"></td>
</tr>
To get a numbering increment index by one.
<tr th:each="item: ${items}">
<td th:text="${iterator.indexOf(item) + 1}"></td>
</tr>

Selenium Webdriver - Unticking all the chekboxes in a complicated table

I am having some problems currently trying to untick checkboxes in an iframe. The situation is it is currently possible to set some checkboxes to default ticked and some not. I need 1 specific checkbox ticked, so the sensible thing to do is run a loop that iterates through all the checkboxes and unchecks them all.
Here is where I am running into issues. I will post a sample of the HTML that the checkboxes are contained in. (This isn't mine so I can't edit the HTML unfortunately).
This is how the example looks in a situation where there are 3 different types of checkbox in the iframe.
<fieldset id="testing">
<legend>testing</legend>
<table>
<tbody>
<tr>
<td class="EXAMPLE">
<table id="CHECKBOXTYPE1">
<tbody>
<tr>
<td style="vertical-align:top;white-space:nowrap;" title="">
<input id="CHECKBOXTYPE1-01" type="checkbox" value="on" onclick="DOES STUFF;"/>
</td>
<td style="vertical-align:top;white-space:nowrap;" title="">TITLE1</td>
</tr>
<tr>
<td/>
<td id="CHECKBOXTYPE2-01" style="display:none;white-space:nowrap;vertical-align:top;padding:0px;">
<table>
<tbody>
<tr>
<td style="vertical-align:top;" colspan="3">
<select id="field" style="width:100%;">
<option value="1">STUFF1 </option>
<option value="2">STUFF2 </option>
<option value="3">STUFF3 </option>
<option value="4">STUFF4 </option>
</select>
</td>
<td style="vertical-align:bottom;padding-left:6px;" rowspan="2">
<textarea id="CHECKBOXTYPE2-01-COMMENTS" cols="50" rows="2" style="margin:0px;height:50px;" type="text" onclick="DOES STUFF">Please Insert Notes...</textarea>
</td>
</tr>
<tr>
<td style="vertical-align:bottom;">
<input type="CHECKBOXTYPE2-01-BUTTON" onclick="DOES STUFF" value="<" style="height:100%;width:32px;"/>
</td>
<td style="vertical-align:bottom;">
<input id="CHECKBOXTYPE2-01-INPUT" type="input" readonly="" style="width:112px;"/>
</td>
<td style="vertical-align:bottom;">
<input type="CHECKBOXTYPE2-01-BUTTON" onclick="DOES STUFF" style="width:32px;height:100%;" value=">"/>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="field_label">
<table id="CHECKBOXTYPE3">
<tbody>
<tr>
<td style="vertical-align:top;">
<input id="CHECKBOXTYPE3-01" type="checkbox" title="" onclick="DOES STUFF"/>
</td>
<td style="vertical-align:top;" title="">CHECKBOX NAME</td>
<td style="vertical-align:top;">
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
The code I have attempted to iterate is
try{
for(int i=0; i < 30; i++){
WebElement relCheckBoxes = driver.findElement(By.xpath("html/body/div[3]/fieldset/table/tbody/tr[i]/td/table/tbody/tr/td[1]"));
if(relCheckBoxes.isSelected()){
relCheckBoxes.click();
}
}
}
catch(Exception e){
System.out.printf("didn't work");
}
Obviously this is not the most optimised piece of code, but right now I'm just struggling to find something that works :\ I just want to run through the checkboxes, turn off all of them, then turn on the one that I need after.
Thank you.
If you want to uncheck all the checkboxes use the following code. It is much efficient!
//Get the complex table
WebElement mainTable = driver.findElement(By.xpath("html/body/div[3]/fieldset/table"));
//Find all the input tags inside the mainTable and save it to a list
List<WebElement> checkBoxes = mainTable.findElements(By.tagName("input"));
//iterate through the list of checkboxes and if checked, uncheck them
for (WebElement checkbox : checkBoxes) {
if (checkbox.isSelected()) {
checkbox.click();
}
}
I dont see any frame inside your code. If there is a frame use the below code 1st
//switch to the frame
driver.switchTo().frame("framename/index");
Hope this helps you :)
There are a couple of problems here:
1) Your XPath is incorrect. You have:
"html/body/div[3]/fieldset/table/tbody/tr[i]/td/table/tbody/tr/td[1]"
Instead, it should be:
"html/body/div[3]/fieldset/table/tbody/tr[" + i + "]/td/table/tbody/tr/td[1]"
Otherwise, you're just looking for a table row with a non-numerical index 30 times!
2) XPath indices are 1-based rather than 0-based (crazy, I know). Since your loop starts with i=0, it starts off by trying to find the non-existent zeroth element. findElement throws an exception when it cannot locate an element that matches the search criterion, so the loop ends immediately. Try starting the loop with i=1 instead.

Categories