spring boot and thymeleaf - displaying All Elements - spring

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;
}

Related

format nested object to table on thymeleaf

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.

How can I create dynamic table in Thymeleaf..?

I am new to Thymeleaf and trying to create a dynamic table on Themeleaf template.
How can I do it..??
I have been googling by I didn't got any proper answer. The issue is I cannot iterate List< Map< String,Object >>. I can have any number of columns and columns name could be any thing.
<tr class="headings">
<th class="column-title">ID</th>
<th class="column-title">Name</th>
<th class="column-title">Salary</th>
<th class="column-title">Status</th>
</tr>
</thead>
<tbody>
<tr class="even pointer" th:each="row:${rows}" id = "tablerow">
<td class=" " th:text="${row.getId()}">Id</td>
<td class=" " th:text="${row.getName()}">Name</td>
<td class=" " th:utext="${row.getSalary()}">Salary</td>
<td class=" " th:text="${row.getStatus()}">Active</td>
</tr>
</tbody>
I need to set values dynamically since if query of result will keep changing . right now column name are hard coded and value are also getting by row.getId what if there is no Id, it could be anything in rows what shall I use than..? example row.<>.
rows is obtained as List< Map< String, Object>>.
Thanks in advance.
You can iterative over a Map just as easily as you can a List. The simplest form of this would be:
<tbody>
<tr class="even pointer" th:each="row: ${rows}" id="tablerow">
<td th:each="field: ${row}" th:text="${field.value}" />
</tr>
</tbody>
However, since Maps don't have a specific ordering (unless you're using something like a TreeMap), the way I would do it would be something like this (complete example should match your example table):
Controller
List<String> headers = Arrays.asList("ID", "Name", "Salary", "Status");
List<Map<String, Object>> rows = new ArrayList<>();
rows.add(Map.of("ID", "1", "Name", "Jim", "Salary", "50000", "Status", "active"));
rows.add(Map.of("ID", "2", "Name", "Sally", "Salary", "50000", "Status", "inactive"));
Template
<table>
<thead>
<tr class="headings">
<th th:each="header: ${headers}" class="column-title" th:text="${header}" />
</tr>
</thead>
<tbody>
<tr class="even pointer" th:each="row: ${rows}" id="tablerow">
<td th:each="header: ${headers}" th:text="${row.get(header)}" />
</tr>
</tbody>
</table>
Which will produce:
<table>
<thead>
<tr class="headings">
<th class="column-title" >ID</th>
<th class="column-title" >Name</th>
<th class="column-title" >Salary</th>
<th class="column-title" >Status</th>
</tr>
</thead>
<tbody>
<tr class="even pointer" id="tablerow">
<td >1</td>
<td >Jim</td>
<td >50000</td>
<td >active</td>
</tr>
<tr class="even pointer" id="tablerow">
<td >2</td>
<td >Sally</td>
<td >50000</td>
<td >inactive</td>
</tr>
</tbody>
</table>

Why <td th:each="i : ${#numbers.sequence(0, table_width)}" th:text="${rows[${i}]}"></td> not working

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.

Iterating in thymleaf

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}"`

Can't find field (List of custom POJOs) in Thymeleaf?

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;
}

Resources