Thymeleaf: Iteration - increment by N and access list.get(N) - java

So I've read the Iterations part of the documentation already but still didn't give any idea on how to do the following:
Iterate per 2 records (since I am rendering something like below) and access list by index.
<div class="row">
<div class="col-md-6">
...
</div>
<div class="col-md-6">
...
</div>
</div>
Basically if this were in code, it looks something like
for (int i = 0; i < size;) {
// do stuff
// manual increment
if (i + 2 > size) {
i++;
} else {
i += 2;
}
}
Any other approach that would satisfy my problem is always welcome too!

I was able to solve it using something like below:
Basically, I still loop individually but just skip every other record using th:if="${stat.even}" and just get the next record by stat.index + 1.
Be really cautious about the IndexOutOfBoundsException though.
<div class="row" th:each="hivRisk, stat : ${hivRiskList}" th:if="${stat.even}">
<div class="col-md-6" th:with="leftRisk=${hivRiskList.get(stat.index)}">
<div class="checkbox checkbox-styled">
<label>
<input type="checkbox" value="-1" th:value="${leftRisk.id}"/>
<span th:text="${leftRisk.name}">HIV Risk</span>
</label>
</div>
</div>
<div class="col-md-6" th:if="${stat.index + 1 < hivRiskList.size()}" th:with="rightRisk=${hivRiskList.get(stat.index + 1)}">
<div class="checkbox checkbox-styled">
<label>
<input type="checkbox" value="-1" th:value="${rightRisk.id}"/>
<span th:text="${rightRisk.name}">HIV Risk</span>
</label>
</div>
</div>
</div>

Related

How to iterate many arrays simultaniously inside a same loop

I am new with thymeleaf, and I want to display 3 values from 3 different arrays with the same index, inside the same div.row, I tried several ways but I only could iterate one array at a time without errors, below is my Controller side:
public String index(Model model) {
String[] table0 = {"0","1","2","3"}
String[] table1 = {"14","21","25","75"}
String[] table2 = {"7","63","57","87"}
model.addAttribute("table0", table0;
model.addAttribute("table1", table1);
model.addAttribute("table2", table2);
return "index";
}
Inside the html file, table0 is the first array iterated without errors, I don't know how to edit/improve the following code to display all the three arrays tables0, tables1 and tables3 at the same time:
<div class="row" th:each="v0 : ${tables0}" >
<div class="cell" th:text="value">
<!-- Here I could display a value from tables0 -->
</div>
<div class="cell" >
<!-- Here I need to display the value of tables1 having the same index as v0 -->
</div>
<div class="cell" >
<!-- Here I need to display the value of tables2 having the same index as v0 -->
</div>
</div>
here you could find what you're searching about , keeping iteration status
by simply adding a var after the object , and use index to get the current index value
by example :
<div class="row" th:each="v0,iter : ${tables0}" >
<div class="cell" th:text="value">
<!-- Here I could display a value from tables0 -->
<span th:text="${v0}"></span>
</div>
<div class="cell" >
<span th:text="${table1[iter.index]}"></span>
</div>
<div class="cell" >
<span th:text="${table2[iter.index]}"></span>
</div>
</div>
You can use Thymeleaf's iterStat to do this.
Assuming the following input data:
String[] table0 = {"0", "1", "2", "3"};
String[] table1 = {"14", "21", "25", "75"};
String[] table2 = {"7", "63", "57", "87"};
You can use the following Thymeleaf markup:
<div class="row" th:each="val,iterStat : ${table0}" >
<div class="cell" th:text="${val}">
</div>
<div class="cell" th:text="${table1[iterStat.index]}">
</div>
<div class="cell" th:text="${table2[iterStat.index]}">
</div>
</div>
This produces a column of numbers as follows (I don't have any CSS so it's just the raw output):
0
14
7
1
21
63
2
25
57
3
75
87
The related html looks like this:
<div class="row">
<div class="cell">0</div>
<div class="cell">14</div>
<div class="cell">7</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">21</div>
<div class="cell">63</div>
</div>
<div class="row">
<div class="cell">2</div>
<div class="cell">25</div>
<div class="cell">57</div>
</div>
<div class="row">
<div class="cell">3</div>
<div class="cell">75</div>
<div class="cell">87</div>
</div>
The iterStat function is described here - it basically keeps track of your iterations. Since you want the same index for each table, it's a good fit for your needs.

How to create dynamic responsive card view using serverside data in bootstap 4?

I want to create a card view which dynamically generate from loop. But card view is generated vertically. I want 3 column in row .But when i run, it generates vertical cardview. Actually my data come from server. Here is my card view image look like..
I have used bellow like to create card view. It create a card view vertically. that means single row
<% for (User_Model model : list) {%>
<div class="row">
<div class="col-sm-4">
<div class="card" >
<div class="card-body">
<h5 class="card-title">Card Title</h5>
<p class="card-text"> Text</p>
</div>
</div>
</div>
</div>
<% }%>
My above Loop is given data like
for (i = 0; i < 5; i++) {
}
Please Help me to create horizontal card view above code..
Try this.
Output will be like.
https://www.screencast.com/t/vvcIZU1Mv
<%! int loop_counter =1; int innerBreak = 1;%>
<% for (User_Model model : list) {
if(innerBreak == 1){ %>
<!-- when complete 3 column in a row open new-->
<div class="row">
<% } %>
<div class="col-sm-4">
<div class="card" >
<div class="card-body">
<h5 class="card-title">Card Title</h5>
<p class="card-text"> Text</p>
</div>
</div>
</div>
<!-- when complete 3 column in a row closed previous open div -->
<%if(loop_counter%3==0){%>
</div>
<% innerBreak = 1;}else{ innerBreak = 0;}
loop_counter++;
}%>

Can't select Multiple Dropdown with Selenium webdriver (not class Select)

I'm having a problem with my tests with Selenium webdriver. I'm using Java. Can't select from a multiple drop-down that is not class Select. This is how the drop-down looks like:
Drop-Down picture
And that's the code:
<div class="form-group ">
<label for="CurrentCategoriesNomIds-selectized">Categories</label>
<select placeholder="" multiple="multiple" id="CurrentCategoriesNomIds" name="CurrentCategoriesNomIds" tabindex="-1" class="selectized" style="display: none;">
<option value="325" selected="selected">Education</option>
</select>
<div class="selectize-control multi plugin-remove_button">
<div class="selectize-input items not-full has-options has-items">
<div class="item" data-value="325">
Education
×
</div>
<input type="text" autocomplete="off" tabindex="" id="CurrentCategoriesNomIds-selectized" style="width: 4px; opacity: 1; position: relative; left: 0px;"></div>
<div class="selectize-dropdown multi plugin-remove_button" style="display: none; visibility: visible; width: 800px; top: 36px; left: 0px;">
<div class="selectize-dropdown-content">
<div class="option" data-selectable="" data-value="324">Agriculture</div>
<div class="option" data-selectable="" data-value="298">Culture</div>
<div class="option" data-selectable="" data-value="326">Employment</div>
<div class="option" data-selectable="" data-value="323">Environment</div>
<div class="option" data-selectable="" data-value="327">Other</div>
<div class="option" data-selectable="" data-value="297">Political</div>
<div class="option" data-selectable="" data-value="322">Transport</div>
</div>
</div>
</div>
</div>
This is how it looks like when 2 options are selected. I was wondering if I can try with KEYS but the page doesn't work like that. Haven't seen that kind of field before, and not sure how to proceed?
You can click on dropdown using this code :
public static void selectOption(WebDriver driver, String optionName) {
List<WebElement> options = driver.findElements(By.xpath("//div[#class='selectize-dropdoun-content']//div[#class='option']"));
options.forEach(option -> {
if (option.getAttribute("innerText").equals(optionName)) {
Actions actions = new Actions(driver);
actions.moveToElement(option).click().build().perform();
}
});
}
and then use like this:
String option = "Education";
selectOption(driver,option);
Hope that helps you:)
Adding screenshot for what I have tried on website : https://semantic-ui.com/modules/dropdown.html
I don't much use Java, so I'll be writing some pseudo code for this that should give you an outline on how to achieve it (but may not run as written).
public static void selectOptionFromSelectizeDropdown(String optionText, String dropdown){
boolean completed = false;
int numberOfOptions = driver.findElements(By.css(dropdown + " .option")).length
for(int i = 0; i < numberOfOptions && completed === false; i++){
// Check if it's displayed, if it is, HUZZAH! Click the option
if(driver.findElement(By.xpath('//*/*[contains(#class, "option") and contains(text(), "'+optionText+'")])')).isDisplayed()){
driver.findElement(By.xpath('//*/*[contains(#class, "option") and contains(text(), "'+optionText+'")])')).click();
completed === true;
break;
} else {
// In case there are many options, and you have to scroll through them.
int x = 0;
while(x <= 6){
driver.findElement(By.css(dropdown)).sendKeys(Keys.DOWN);
i++;
}
}
if(i===numberOfOptions - 1){
throw new Error("Option Not Found");
}
}
}
selectOptionFromSelectizeDropdown("Education", ".selectize-dropdown-content");
If this doesn't work, I'd recommend changing the click() to a sendKeys(Key.ENTER) to see if that would work.
Explanation
Will loop through, seeing if the option is displayed on the page. If not, will scroll down x times, and check again, until the option is found.
If it reaches the number of options inside the box, it will throw an error.

Finding previous sibling element using selenium xpath dynamically

I am writing selenium scripts for the following code.
<div id="abc" class="ui-selectmanycheckbox ui-widget hpsapf-chechkbox">
<div class="ui-chkbox ui-widget">
<div class="ui-helper-hidden-accessible">
<input id="abc:0" name="abc" type="checkbox" value="0" checked="checked">
</div>
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default ui-state-active">
<span class="ui-chkbox-icon ui-icon ui-icon-check ui-c"></span>
</div>
</div>
<span class="hpsapf-radio-label">
<label for="abc:0">Herr</label>
</span>
<div class="ui-chkbox ui-widget">
<div class="ui-helper-hidden-accessible">
<input id="abc:1" name="abc" type="checkbox" value="1">
</div>
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">
<span class="ui-chkbox-icon ui-icon ui-icon-blank ui-c"></span>
</div>
</div>
<span class="hpsapf-radio-label">
<label for="abc:1">Frau</label>
</span>
</div>
These are the checkbox like the following.The number of the checkboxes are changed as per database values.
In my code i am first checking whether the "Frau" check box is selected or not. so i tried following snippet.
WebElement mainElement= driver.findElement(By.id("abc"));
WebElement label=mainElement.findElement(By.xpath(".//label[contains(#for,'abc')][text() = 'Frau']"));
WebElement parent = label.findElement(By.xpath(".."));
WebElement div = parent.findElement(By.xpath("preceding-sibling::::div"));
WebElement checkBox = div.findElement(By.className("ui-chkbox-box"));
String css = checkBox.getAttribute("class");
if(css.contains("ui-state-active")) {
return "checked";
}
else
{
return "unchecked";
}
But when i tried to execute this script. WebElement div = parent.findElement(By.xpath("preceding-sibling::::div")); gives me the first div tag and not the preceding one. I want a preceding sibling.
Use :: and index, not ::::
WebElement div = parent.findElement(By.xpath("preceding-sibling::div[1]"));

Check for table data - Jsoup

Is there a way to check if a table has a certain row using jsoup?
I am getting an java.lang.IndexOutOfBoundsException: Invalid location 1, size is 1 exception, my code for getting the info out of the table is:
docTide = Jsoup.connect("http://www.mhpa.co.uk/search-tide-times/").timeout(600000).get();
Elements tideTimeOdd = docTide.select("div.tide_row.odd div:eq(0)");
Elements tideTimeEven = docTide.select("div.tide_row.even div:eq(0)");
Elements tideHightOdd = docTide.select("div.tide_row.odd div:eq(2)");
Elements tideHightEven = docTide.select("div.tide_row.even div:eq(2)");
Element firstTideTime = tideTimeOdd.first();
Element secondTideTime = tideTimeEven.first();
Element thirdTideTime = tideTimeOdd.get(1);
Element fourthTideTime = tideTimeEven.get(1);
The exception is occurring because sometime the table only has 3 rows instead of 4, in this order;
odd
even
odd
even
it is the last 'even' row that is causing the problem.
<div class="tide_row odd">
<div class="time">00:57</div>
<div class="height_m">4.9</div>
<div class="height_f">16,1</div>
<div class="range_m">1.9</div>
<div class="range_f">6,3</div>
</div>
<div class="tide_row even">
<div class="time">07:23</div>
<div class="height_m">2.9</div>
<div class="height_f">9,6</div>
<div class="range_m">2</div>
<div class="range_f">6,7</div>
</div>
<div class="tide_row odd">
<div class="time">13:46</div>
<div class="height_m">5.1</div>
<div class="height_f">16,9</div>
<div class="range_m">2.2</div>
<div class="range_f">7,3</div>
</div>
<div class="tide_row even">
<div class="time">20:23</div>
<div class="height_m">2.8</div>
<div class="height_f">9,2</div>
<div class="range_m">2.3</div>
<div class="range_f">7,7</div>
</div>
To simply check the size of the Elements object, use the size() method to determine if it exists or not.
To check for a certain Element use the contains() method.
You might also consider using a loop to iterate over all the Element objects in your Elements collection.
if(tideTimeEven.size() > 1)
//Do something
You could do
if (tideTimeEven.size() > 1) {
Element fourthTideTime = tideTimeEven.get(1);
}

Categories

Resources