I was trying to iterate through functionList in thymleaf.This is what I done.
Controller :
#RequestMapping(value = "/list",method = RequestMethod.GET)
public ModelAndView getFunctionList(HttpServletRequest request){
ModelAndView mav = new ModelAndView("adminConfigurationFunction");
List<Function> functionList = functionService.getList();
mav.addObject("list", functionList);
return mav;
}
and in html :
<table class="table table-striped table-condensed margin-top-20">
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<tr th:each="func : ${functionList}" >
<td th:text="${func.name}"></td>
<td th:text="${func.description}"></td>
</tr>
</table>
I am new here. What am I doing wrong?Or should I use th:for?
I found the answer.
<tr th:each="func : ${list}" >
<td th:text="${func.name}"></td>
<td th:text="${func.description}"></td>
</tr>
changed th:each="func : ${functionList}" th:each="func : ${list}"`
Related
I have this controller:
#DeleteMapping("/delete/{id}")
public String deleteWallet(#PathVariable("id") long id, Model model) {
Wallet wallet = walletRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid wallet Id:" + id));
walletRepository.delete(wallet);
model.addAttribute("wallets", walletRepository.findAll());
return "redirect:/";
}
And this is HTML:
<table class="table table-striped table-hover" id="productTable">
<thead>
<tr class="success">
<th>Wallet Name</th>
<th>Initial Balance</th>
</tr>
</thead>
<tbody>
<tr th:each="wallet : ${wallet}">
<td th:text="${wallet.walletName}"></td>
<td th:text="${wallet.initialBalance}"></td>
<td>
<a th:href="#{/api/wallet/delete/{id}(id = ${wallet.id})}">Delete</a>
</td>
</tr>
</tbody>
But when I press delete button its says:
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
I'm confused, my method is #DeleteMapping
Anyway, I found a way:
HTML:
<form th:action="#{/api/wallet/delete/{id}(id=${wallet.id})}"
th:object="${wallet}" method="post">
<input type="hidden" th:field="${wallet}">Delete</input>
<button type="submit" onClick="return confirm('sure?')"/>
</form>
Controller:
#PostMapping("/delete/{id}")
public String deleteWallet(#PathVariable("id") long id, Model model) {
walletService.deleteWalletById(id);
return "redirect:/";
}
i build crm system,
i had object hes name users he hold also the data from details table (one to many realation)
lets says i had nested object name user and he had more than 1 object of details
i want to get this in the end in thymeleaf table
name | entry date
david | 5/6/22
david | 1/7/22
but i got
name | entry date
david | 5/6/22 , 1/7/22
this is table code on thymeleaf:
<table class="table w-75 table-striped table-dark table-hover">
<thead>
<tr>
<th scope="col" class="text-center">First name</th>
<th scope="col" class="text-center">Entry Date</th>
</tr>
</thead>
<tbody>
<tr th:each="users : ${ParkingUsers}">
<td class="text-center" th:text="${users.firstName}" />
<td class="text-center" th:each="date, i: ${users.parkingDetails}"
th:text="${(i.index > 0 ? '' : '') + date.entryDate}" />
</tr>
</tbody>
</table>
how can i fix that?
thanks
This is a good candidate for using the Thymeleaf th:block tag.
You can place the outer loop (for users) in this tag, and then place the inner loop (for parking details) in the <tr> tag.
Example:
Assume we have two classes:
public class User {
private String firstName;
private List<ParkingDetail> parkingDetails;
// getters and setters
}
And:
public class ParkingDetail {
private LocalDate entryDate;
// getters and setters
}
And assume we have a list of users: List<User>.
We can use the following in our Thymeleaf template:
<table class="table w-75 table-striped table-dark table-hover">
<thead>
<tr>
<th>First name</th>
<th>Entry Date</th>
</tr>
</thead>
<tbody>
<th:block th:each="user : ${users}">
<tr th:each="parkingDetail : ${user.parkingDetails}">
<td th:text="${user.firstName}"></td>
<td th:text="${parkingDetail.entryDate}"></td>
</tr>
</th:block>
</tbody>
</table>
This will generate the following HTML:
<table>
<thead>
<tr>
<th>First name</th>
<th>Entry Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>david</td>
<td>2022-06-05</td>
</tr>
<tr>
<td>david</td>
<td>2022-07-01</td>
</tr>
</tbody>
</table>
The th:block tag allowed Thymeleaf to iterate over the list of users, but it did not cause any HTML to be generated. The Thymeleaf ${user} variable created in the th:block tag can be referenced in all the child tags inside the th:block.
There are various other examples of how th:block can be used, in other questions on this site - so if this does not meet your needs, you can research those other questions.
Can you help me about showing all the elements in "book-data".html file?
My controller class is
#Autowired BooksService booksService
#GetMapping("/books")
private List<Books> getAllBooks() throws IOException, InterruptedException {
return booksService.getAllBooks();
}
and my service class is
#Autowired BooksRepository booksRepository;
public List<Books> getAllBooks() throws IOException, InterruptedException {
return (List<Books>) booksRepository.findAll();
}
my book repository interface is
public interface BooksRepository extends CrudRepository<Books, Integer>
{
}
and my "book-data".html file is
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Book ID</th>
<th scope="col">Book Name</th>
<th scope="col">Book Author</th>
<th scope="col">Book Price</th>
</tr>
</thead>
<tbody>
<tr>
<td th:text="${book.bookid}"></td>
<td th:text="${book.bookname}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.price}"></td>
</tr>
</tbody>
In HTML page, it doesn't show any book data. For service class, I saw another solution like below, but it didn't solve the problem.
#RequestMapping("/books")
private String listBooks(Model model){
model.addAtrribute("books", booksService.getAllBooks());
return "books";
}
in html:
<tbody>
<tr th:each="book : ${books}">
<td th:text="${book.bookid}"></td>
<td th:text="${book.bookname}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.price}"></td>
</tr>
</tbody>
I think something like this is maybe a solution :
in your controller with adding #Controller in class statement :
#Autowired
BooksService booksService
#GetMapping("/books")
private String listBooks(Model model){
model.addAtrribute("books", booksService.getAllBooks());
return "views/book-data";
}
your service with adding #Service in class statement :
#Autowired
BooksRepository bookRepository
public List<Books> getAllBooks(){
return this.booksRepository.findAll();
}
your repository with adding #Repository in class statement :
maybe you could had #Query
#Repository
public interface BooksRepository extends CrudRepository<Books, Long>
{
public List<Books> findAll();
}
And your html :
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Book ID</th>
<th scope="col">Book Name</th>
<th scope="col">Book Author</th>
<th scope="col">Book Price</th>
</tr>
</thead>
<tbody>
<tr th:each="book : ${books}">
<td th:text="${book.bookid}"></td>
<td th:text="${book.bookname}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.price}"></td>
</tr>
</tbody>
</table>
First, I created another html file that shows "all books". This file is named allBooks.html. Then, the service method below solved the problem, for your information.
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html xmlns:th="https://thymeleaf.org">
<style>
table, th, td {
border: 1px solid black;
text-align: center;
}
</style>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Book ID</th>
<th scope="col">Book Name</th>
<th scope="col">Book Author</th>
<th scope="col">Book Price</th>
</tr>
</thead>
<tbody>
<tr th:each="book : ${books}">
<td th:text="${book.bookid}"></td>
<td th:text="${book.bookname}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.price}"></td>
</tr>
</tbody>
#GetMapping("/books")
private ModelAndView getAllBooks() throws IOException, InterruptedException {
ModelAndView mav = new ModelAndView();
mav.setViewName("allBooks");
mav.addObject("books", booksService.getAllBooks());
return mav;
}
I am trying to Iterate through a list which contains a list of objects, i.e. List I am wondered why this is not working, tried with simply "i", but no luck.
List<Object[]> lists; // logic
model.addObject("lists", lists);
model.addObject("table_width", lists.get(0).length);
Thymeleaf Code Snippet
<table class="table table-responsive table-stripped table-collapsed table-bordered">
<tr th:each="rows,rowStat : ${lists}">
<td th:text="${rowStat.count}"></td>
<td th:each="i : ${#numbers.sequence(0, table_width)}" th:text="${rows[${i}]}"></td>
</tr>
</table>
I have found a way,
<td th:each="i : ${#numbers.sequence(0, table_width-1)}" th:text="${rows[__${i}__]}"></td>
This does the tricks
You can simply iterator over both lists. No need to use the #numbers helper.
<table class="table table-responsive table-stripped table-collapsed table-bordered">
<tr th:each="rows, rowStat : ${lists}">
<td th:text="${rowStat.count}"></td>
<td th:each="value: ${rows}" th:text="${value}"></td>
</tr>
</table>
If you are iterating a collection(list) of objects, try below example:
HTML:
<div th:if="${not #lists.isEmpty(counts)}">
<h2>Counts List</h2>
<table class="table table-striped">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="count : ${counts}">
<td th:text="${count.id}"></td>
<td th:text="${count.name}"></td>
</tr>
</table>
</div>
Java:
public List<Count> listAll() {
List<Count> counts = new ArrayList<>();
countRepository.findAll().forEach(counts::add);
return counts;
}
Read more info in Thymeleaf Documentation - Iteration Basics section.
I have the following code below. Thymeleaf is unable to resolve "orderDetails" despite the field being existent/not null when i debug through the internals of Thymeleaf.
Exception= Field or property 'orderDetails' cannot be found on object of type
<div th:each="order : ${orders}">
<table>
<tr>
<th>CUSTOMER</th>
<th>PRICE</th>
<th>TIME ORDER PLACED</th>
<th>ITEMS</th>
</tr>
<tr>
<td th:text="${order.customerAccount.email}">email</td>
<td th:text="${order.baseCost}">2.50</td>
<td th:text="${order.tip}">2.00</td>
<td th:text="${order.orderDetails}">2.00</td>
<!-- <td th:text="${#lists.size(order.orderDetails)}">1</td> -->
</tr>
</table>
<table>
<tr>
<th>DRINK NAME</th>
<th>AMOUNT</th>
<th>QUANTITY</th>
<th>COST</th>
</tr>
<tr th:each="orderDetail : ${order.orderDetails}">
<td th:text="${orderDetail.barStock.drink.name}">Test Drink Name</td>
<td th:text="${orderDetail.barStock.amount}">10oz</td>
<td th:text="${orderDetail.quantity}">2</td>
<td th:text="${orderDetail.barStock.cost * orderDetail.quantity}">2.00</td>
</tr>
</table>
Here is the field in question of the "order" field/class.
#OneToMany(fetch = FetchType.EAGER, mappedBy = "barOrder")
#JsonProperty
private Set<OrderDetail> orderDetails;
A public getter method for orderDetails field is needed to allow Thymeleaf to access it.
public Set<OrderDetail> getOrderDetails() {
return orderDetails;
}