Thymeleaf Table Rows Divide in separate Pages - html

I have table with 212 rows and I would like to split them between pages so that all pages have 25 rows and last page 12 rows.
I would like to know if this is possible at all with Thymeleaf or should I use something else for that.
And is it possible to calculate total values per page also?
Here is the pdf file: https://www.docdroid.net/TSLdFA1/report1.pdf

the is sample code for the controller
#Controller
public class BookController {
#Autowired
private BookService bookService;
#RequestMapping(value = "/listBooks", method = RequestMethod.GET)
public String listBooks(
Model model,
#RequestParam("page") Optional<Integer> page,
#RequestParam("size") Optional<Integer> size) {
int currentPage = page.orElse(1);
int pageSize = size.orElse(5);
Page<Book> bookPage = bookService.findPaginated(PageRequest.of(currentPage - 1, pageSize));
model.addAttribute("bookPage", bookPage);
int totalPages = bookPage.getTotalPages();
if (totalPages > 0) {
List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
.boxed()
.collect(Collectors.toList());
model.addAttribute("pageNumbers", pageNumbers);
}
return "listBooks.html";
}
}
and here is Thymeleaf Template
<table border="1">
<thead>
<tr>
<th th:text="#{msg.id}" />
<th th:text="#{msg.name}" />
</tr>
</thead>
<tbody>
<tr th:each="book, iStat : ${bookPage.content}"
th:style="${iStat.odd}? 'font-weight: bold;'"
th:alt-title="${iStat.even}? 'even' : 'odd'">
<td th:text="${book.id}" />
<td th:text="${book.name}" />
</tr>
</tbody>
</table>
<div th:if="${bookPage.totalPages > 0}" class="pagination"
th:each="pageNumber : ${pageNumbers}">
<a th:href="#{/listBooks(size=${bookPage.size}, page=${pageNumber})}"
th:text=${pageNumber}
th:class="${pageNumber==bookPage.number + 1} ? active"></a>
</div>

Related

Thymeleaf looping over list of objects with list of objects attribute problem

I'm working in Spring Boot and I have a problem rendering with Thymeleaf a table with different lines. First must be a String, and the subsequent lines must be the data saved in a list of objects.
situation of the problem:
I have a list of objects, this object has two attributes, one is a list of Strings, and the other one is a list of different objects. I don't know how to render in Thymeleaf in a table the first attribute of a string list in a line, and on the next lines of the table render the second list of attribute object.
details of the object:
public class objetosDeServiciosAD {
private String Servicio;
private LinkedList<usuarioAD> listaUsuariosAD;
public String getServicio() {
return Servicio;
}
public void setServicio(String servicio) {
Servicio = servicio;
}
public LinkedList<usuarioAD> getListaUsuariosAD() {
return listaUsuariosAD;
}
public void setListaUsuariosAD(LinkedList<usuarioAD> listaUsuariosAD) {
this.listaUsuariosAD = listaUsuariosAD;
}
#Override
public String toString() {
return "objetosDeServiciosAD [Servicio=" + Servicio + ", listaUsuariosAD=" + listaUsuariosAD + "]";
}
}
objetos_Servicios is a list of objects with two atributes, one is servicio
this object has a second attibute which is a list of objects, this is listaUsuariosAD.
This is my code in Thymeleaf:
<table class="table table-hover">
<thead class="thead-light">
<tr>
<th scope="col">Usuario</th>
<th scope="col">Teléfono</th>
<th scope="col">mail</th>
<th scope="col">Descripción</th>
</tr>
</thead>
<tbody>
<tr th:each="servicio : ${objetos_Servicios}">
<td th:text="${servicio.servicio}"></td>
<tr th:each=" listaeusuario : ${servicio.listaUsuariosAD}">
<tr th:each ="usuarios : ${listaeusuario}">
<td th:text = "${usuarios.usuario}"></td>
<td th:text = "${usuarios.telefono}"></td>
<td th:text = "${usuarios.mail}"></td>
<td th:text = "${usuarios.descripion}"></td>
</tr>
</tr>
</tbody>
</table>
The code will look something like this:
<table class="table table-hover">
<thead class="thead-light">
<tr>
<th scope="col">Usuario</th>
<th scope="col">Teléfono</th>
<th scope="col">mail</th>
<th scope="col">Descripción</th>
</tr>
</thead>
<tbody>
<th:block th:each="servicio : ${objetos_Servicios}">
<tr>
<td th:text="${servicio.servicio}" />
</tr>
<tr th:each = "lista : ${servicio.getListaUsuariosAD()}">
<td th:text="${lista.usuario}"></td>
<td th:text="${lista.telefono}"></td>
<td th:text="${lista.mail}"></td>
<td th:text="${lista.Descripcion}"></td>
</tr>
</th:block>
</tbody>
</table>
You can use a th:block tag to loop over a larger block of code (that contains the header <tr /> and the rows <tr />).
I recommend changing the naming standards you are using, so that all your class names begin with an upper-case letter - for example: ObjetosDeServiciosAD instead of objetosDeServiciosAD. This is standard in Java - and not doing this can be confusing for other people who read your code.
So, your class becomes:
import java.util.List;
public class ObjetosDeServiciosAD {
private String servicio;
private List<UsuarioAD> listaUsuariosAD;
public String getServicio() {
return servicio;
}
public void setServicio(String servicio) {
this.servicio = servicio;
}
public List<UsuarioAD> getListaUsuariosAD() {
return listaUsuariosAD;
}
public void setListaUsuariosAD(List<UsuarioAD> listaUsuariosAD) {
this.listaUsuariosAD = listaUsuariosAD;
}
}
I also replaced LinkedList with List, since you do not appear to need a linked list here (if you actually do, you can revert that change).
Then, for your Thymeleaf template, you can use Thymeleaf's <th:block> tag to structure your iteration loops:
<table class="table table-hover">
<thead class="thead-light">
<tr>
<th scope="col">Usuario</th>
<th scope="col">Teléfono</th>
<th scope="col">mail</th>
<th scope="col">Descripción</th>
</tr>
</thead>
<tbody>
<th:block th:each="servicio : ${objetos_Servicios}">
<tr>
<td th:text="${servicio.servicio}" />
<td></td>
<td></td>
<td></td>
</tr>
<tr th:each = "lista : ${servicio.listaUsuariosAD}">
<td th:text="${lista.usuario}"></td>
<td th:text="${lista.telefono}"></td>
<td th:text="${lista.mail}"></td>
<td th:text="${lista.descripcion}"></td>
</tr>
</th:block>
</tbody>
</table>
In the above code, I also replaced ${servicio.getListaUsuariosAD()} with the simpler ${servicio.listaUsuariosAD}, since you do not need to explicitly call the method, here.
I also added three empty <td></td> cells to ensure each row is complete, for the row displaying the servicio text.

How can i loop over an ArrayList using thymeleaf & spring Boot?

I am new to thymeleaf and i try to loop over a ArrayList but it doesn't work for me .. some help please:
this is my Html page:
<body>
<div class="row">
<table>
<tr th:each="data: mois">
<td class="text-center" th:text="${data}">data</td>
</tr>
</table>
</div>
</body>
this is My controller
#RequestMapping(value="/editePlanning", method= RequestMethod.GET)
public String editePlanning(Model model){
Psi psi = psiRepository.findOne((long) 1);
List<String> data = new ArrayList<String>();
for(int i=0;i<psi.getNombreMois();i++){
int val = psi.getMoisDebut()+i%12;
data.add(""+ val);
}
model.addAttribute("mois",data);
return "editePlanning";
}
You have a typo in your iteration (see the docs, they are very good):
<tr th:each="data: ${mois}">
Don't forget you can get the iteration index, useful to generate the id of elements
<tr th:each="data, iterstat: ${mois}">
<td th:text="${data}" th:id="|td${iterstat.index}|"></td>
</tr>

return PartialView[viewname, model] equivalent?

I've got a site build with RazorViewEngine where using "_ViewStart.cshtml" to set the layout to "Shared/_Layout.cshtml". Then, I've the following module:
public class LogModule : NancyModule
{
public LogModule()
{
Get["/log"] = _ =>
{
var list = GetLog().ToPagedList(1, 5);
return View["Index", list];
};
Get["/log/{page:int}"] = _ =>
{
int pageNumber = _.page ?? 1;
var list = GetLog().ToPagedList(pageNumber, 5);
return View["_List", list];
};
}
}
And the following views:
Index.cshtml
#using Nancy.ViewEngines.Razor
#using PagedList
#inherits NancyRazorViewBase<IPagedList<LogModel>>
<h1>View Log</h1>
<div id='container'>
#Html.Partial("_List", Model)
</div>
_List.cshtml
#using Nancy.ViewEngines.Razor
#using PagedList
#inherits NancyRazorViewBase<IPagedList<LogModel>>
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Date</th>
<th>Message</th>
</tr>
</thead>
<tbody>
#foreach (var log in Model)
{
<tr class="#log.Class">
<td>#log.Date</td>
<td>#log.Message</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="2">
<div class="pagination" data-current="#Model.PageNumber" data-count="#Model.PageCount">
<ul class="list-unstyled list-inline">
<li>|<</li>
<li><</li>
<li class="active"><span>#Model.PageNumber / #Model.PageCount</span></li>
<li>></li>
<li>>|</li>
</ul>
</div>
</td>
</tr>
</tfoot>
</table>
And finally, some javascript code to manage ajax requests to the '/log/{page:int}" action and replace the 'container' div with the result. Sadly, this result contains a full page, including _Layout.cshtml and breaking all the page.
In MVC this is solved using return PartialView(viewName, Model) but I couldn't find something similar in NancyFx. Is there something I'm missing?
Turned out that the solution is quite simple. Just create an 'empty' layout file with this single line:
#RenderBody()
And then use it in your partial view:
#{ Layout = "Shared/_EmptyLayout"; }

How to populate a List based on a Table and its rows in Dart?

I want to populate a list of Objects based on a HTML Table. Let's say I have the following class:
class Employee
{
String name;
String department;
num salary;
...methods
}
And in my HTML, I have the following table:
<table class="table" id="employeeTable">
<thead>
<tr>
<th>Name
<th>Departament
<th>Salary
<tbody id="employeeTableBody">
<tr>
<td> John
<td> 1
<td> 1500
<tr>
<td> Mary
<td> 2
<td> 2500
...etc
</table>
So, how do I query the table, get its rows, then get its cells to fill my List of Employees (in this case)?
I tried to use something like:
TableElement table = query("#employeesTable");
Element tableBody = query("#employeesTableBody");
But I couldn't find a proper method in TableElement or Element to return TableRowElement, or maybe the cells of it. I tried to get the children nodes also, but without sucess.
A pseudo-algorithm to fulfil this task would be something like this:
1. Get the table
2. For each row of the table
2.a Create a new Employee object based on the value of each cell of the row.
2.b Append this object to the Employee List.
3. End
Here the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Scratchweb</title>
<link rel="stylesheet" href="scratchweb.css">
</head>
<body>
<table id="employeeTable">
<tr>
<th>Name</th>
<th>Departament</th>
<th>Salary</th>
</tr>
<tr>
<td>John</td>
<td>1</td>
<td>1500</td>
</tr>
<tr>
<td>Mary</td>
<td>2</td>
<td>2500</td>
</tr>
</table>
<script type="application/dart" src="web/scratchweb.dart"></script>
<script src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/client/dart.js"></script>
</body>
</html>
Here's the Dart:
import 'dart:html';
import 'dart:math';
class Employee {
String name;
String department;
num salary;
Employee({this.name, this.department, this.salary});
String toString() => '<employee name="$name" department="$department" salary="$salary">';
}
void main() {
var employees = new List<Employee>();
var table = query("table#employeeTable");
for (TableRowElement row in table.rows) {
if (row.cells.length != 3) {
print("Malformed row: $row");
continue;
}
if ((row.cells[0] as TableCellElement).tagName == "TH") {
print("Skipping header");
continue;
}
var cells = row.cells;
var employee = new Employee(
name: cells[0].text,
department: cells[1].text,
salary: parseDouble(cells[2].text));
employees.add(employee);
}
print(employees);
}
If you approve of this answer, please remember to accept it. My boss feeds me a slice of bacon every time I successfully answer a question ;)

Split string on MVC3 + razor view

I would like to get help and guide on how can i manipulate text/string that being called from MS-SQL Database. So here is my SettingController.cs partial code for index viewing:
public ActionResult Index()
{
var datacontext = new SGM_SIDDataContext();
var dataToView = from m in datacontext.SGMs
orderby m.Seq
select m;
return View(dataToView.ToList());
}
And This is my index.cshtml codes:
#model IEnumerable<MVC_Apps.Models.SGM>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
SID
</th>
<th>
Abbrev
</th>
<th>
Val
</th>
<th>
Seq
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.SID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Abbrev)
</td>
<td>
#Html.DisplayFor(modelItem => item.Val)
</td>
<td>
#Html.DisplayFor(modelItem => item.Seq)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.GID })
</td>
</tr>
}
</table>
So roughly I got a View. Now here is what i would like to do:
1) The data 'item.Val' on Index.cshtml view will be like this:
A,L,C,H
and sort of like that. But the might be line where the data only contain:
H or C or none(Null value)
But if the data contain more than one char like say it does set for K and L, the data in item.Val will look like this:
A,L
Which the data being separate by comma. So now i want to split that item.Val data and do if statement on it. Where I would like to check every data in item.Val if it contain K or L or C or H or all of them or none of them(Sorry if my english is bad). And I would like to view it as , if all the data contain H so in table view, the will be column named Hotel while if the data also have L so another column of Lounge will be display with a check button being checked.
the possible char in item.Val is:
A = Admin
L = Lounge
H = Hotel
C = Customer
Any help and ideas much appreciated. Thank you in advanced.
Update information:
Thanks Im starting to get what is it. What i really want to do is, when the item.Val does contain H(which is for hotel) then the view will have table column with header name Hotel and at the record it will have tick checkbox.
This is sample picture of table view: http://imagebin.org/152941
But then the Hotel, Admin and User information either it is tick or not is in item.Val
For example for Smith, the item.Val data look like this : C,
For example for Anna , the item.Val data look like this : H,C,
P.S : - the var conf line is a test code. Ignore it as I already delete it from my source. :)
Create a ViewModel similar to
public class MyViewModel
{
// items from your model
public int Id{get;get;}
public String Vals{get;set;} // A,L,C,H
...
...
public bool IsHotel
{
get
{
return Vals.Split(',').Contains("H");
}
}
public bool IsAdmin
{
get
{
return Vals.Split(',').Contains("A");
}
}
public bool IsCust
{
get
{
return Vals.Split(',').Contains("C");
}
}
}
In the controller action
public ActionResult Index()
{
var datacontext = new SGM_SIDDataContext();
var dataToView = from m in datacontext.SGMs
orderby m.Seq
select new MyViewModel()
{
// items from your datacontext
Id= m.SID,
//etc...
};
var conf = from m in datacontext.SGMs // what's the purpose of this query??
select m.Val;
return View(dataToView.ToList());
}
The View will need to be updated, so include columns for Hotel, Cust, Admin and any others you need. I would suggest that you keep it simple and don't try to create the HTML columns on the fly. If you want to do this, you probably will need to inspect all Vals in every object of your list first to determine what columns are needed. In the view
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.SID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Abbrev)
</td>
<td>
#(item.IsHotel? "Checked" : "")
</td>
<td>
#(item.IsAdmin? "Checked" : "")
</td>
<td>
#(item.IsCust? "Checked" : "")
</td>
<td>
#Html.DisplayFor(modelItem => item.Seq)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.GID })
</td>
</tr>
}