I am trying to display a table using Wicket. I am using Panel to create the table and PropertyColumns to add the columns.
How do I group few of the columns into one single column.
It seems that you are using a DataTable or descendant. For your case i would use a ListView where you can easier control the output HTML.
In HTML:
<table>
<thead>
<tr>
<th rowspan="2">Product</th>
<th colspan="2">Unit tests</th>
</tr>
<tr>
<th>Passed</th>
<th>Failed</th>
</tr>
</thead>
<tbody>
<tr wicket:id="listView">
<td wicket:id="productComponent">Product</td>
<td wicket:id="passedComponent">PassedColumn</td>
<td wicket:id="failedComponent">FailedColumn</td>
</tr>
</tbody>
In Java:
add(new ListView<SomeDetails>("listView", listData)
{
public void populateItem(final ListItem<SomeDetails> item)
{
final SomeDetails data= item.getModelObject();
item.add(new Label("productComponent", data.getProduct()));
item.add(new Label("passedComponent", data.getPassed()));
item.add(new Label("failedComponent", !data.getPassed()));
}
});
Related
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.
I want to create a table that its data is a Map< String, List < Object> >.
So the table has one header that and the rows should have the exact data.
Map.key
Object.item1
Object.item2
Object.item3
So since it is a List of Object i want one row for every Object of the List and the Map.key to be repeated.
So i need to iterate through keys like
<table>
<thead>
<tr>
<th>Code</th>
<th>Status</th>
<th>Flag</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr th:each= "result : ${myMap}">
<td th:text="${result.key}"></td>
<td><table>
<tr th:each="obj: ${result.value}">
<td th:text="${not #lists.isEmpty(obj.errorList)}?'Error':'Warning'"></td>
<td th:text="${obj.flag}==true?'YES':'NO'"></td>
<td th:text="${not #lists.isEmpty(obj.errorList)}?${obj.warningList}:${obj.errorList}"></td>
</tr>
</table></td>
</tr>
</tbody>
</table>
but this solution places a table in a table. I want to use one header and iterate the lists and place the variables in the main table .
I think you're looking for a structure like this:
<table>
<thead>
<tr>
<th>Code</th>
<th>Status</th>
<th>Flag</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<th:block th:each= "result : ${myMap}">
<tr th:each="obj: ${result.value}">
<td th:text="${result.key}" />
<td th:text="${not #lists.isEmpty(obj.errorList)}?'Error':'Warning'" />
<td th:text="${obj.flag}==true?'YES':'NO'" />
<td th:text="${not #lists.isEmpty(obj.errorList)}?${obj.warningList}:${obj.errorList}" />
</tr>
</th:block>
</tbody>
</table>
What would be the best way to dynamically add an HTML element, such as another column onto a basic HTML table?
I want to have a button below the table, and if the user were to click the button, the event would add the same amount of rows already in the table and add another column. I would want to support about 5 extra columns being added to the table.
Here's my HTML table as of right now:
<table>
<thead>
<tr>
<th id="row-tag"></th>
<th id="option-column">Option 1</th>
</tr>
</thead>
<tbody>
<tr>
<td id="row-tag">P</td>
<td id="option-column">{{ p }}</td>
</tr>
<tr id="row-tag">
<td>
<app-a-p (saveButtonClick)="toggleAP($event)"
[modModalValues]="modModalValues">
</app-a-p>
</td>
<td id="option-column">
<div class="input-group input-group-sm">
$<input
*ngIf="toggleAP==true"
type="text"
name="aP"
size="10"
disabled
value=""
/>
<input
*ngIf="toggleAP==false"
type="text"
name="aP"
size="10"
[ngModel]="con.pA"
(ngModelChange)="con.pA = $event" appFormatP
(blur)="checkAP($event.target.value);
inputTracker.addModifiedValue('Option 1', $event.target.value)"
/>
</div>
</td>
</tr>
<tr>
<td id="row-tag">L</td>
<td id="option-column">${{l}}</td>
</tr>
<tr>
<td id="row-tag">R</td>
<td id="option-column">${{r}}</td>
</tr>
</tbody>
</table>
I think in Angular, you define table based on your data. for example, you have fields array defining columns, and data array defines the what's actually in the table.
<table >
<thead>
<tr>
<th *ngFor='let key of this.fields'>{{key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let row of this.data ' >
<td scope="row" *ngFor='let key of this.fields'> {{row[key]}} </td>
</tr>
</tbody>
</table>
when you need a new column, just push a new field into fields. like
fields.push('newcolumn');
when you need a new row, just do:
data.push({col1: '', col2:'', newcolumn: ''});
Look into the insertRow() and insertCell() functions in JavaScript. This alongside an onClick function that you write will let you edit the table.
A good way of generating a table on UI when using angular would be to use 2D-array (row*column) use can have a button using which you can dynamically add values to this array and have another row/column to the table.
I am using knockout binding to bind some data into html tables. My knockout view Model had multiple products and each product will have multiple chars. I want to display the products in one table and when i select the link "show chars" it should display the corresponding chars in below table.
This is my View Model
var ProductViewModel = function(items) {
this.items = ko.observableArray(items);
this.itemToAdd = ko.observable("");
this.addItem = function() {
if (this.itemToAdd() != "") {
this.items.push(this.itemToAdd());
this.itemToAdd("");
}
}.bind(this);
};
And this is my html tables
<div id="productTable">
<table class="ui-responsive table">
<thead>
<tr>
<th >Product Name</th>
<th >Description</th>
<th >Parent?</th>
</tr>
</thead>
<tbody id="pBody" data-bind="foreach: items">
<tr class="success" >
<td><span data-bind="text: name"></span>
</td>
<td><span data-bind="text: desc"></span>
</td>
<td>show chars</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="productChars">
<div id="productCharTable">
<table class="ui-responsive table">
<thead>
<tr>
<th >Char Name</th>
<th >Description</th>
<th >Length</th>
<th >Type</th>
</tr>
</thead>
<tbody id="pBody" data-bind="foreach: $data['chars']">
<tr class="success">
<td><span data-bind="text: name"></span>
</td>
<td>asdf asdfasdf</td>
<td>10</td>
<td>String</td>
</tr>
</tbody>
</table>
</div>
I am able to bind the products into first table. But for characteristics i am not sure how to achieve the same.
Could someone please help me in figuring out how to achieve the same.
Here is the jsfiddle
https://jsfiddle.net/sirisha_k/0Ln7h2bo/7/
As #supercool pointed out you can use "data-bind='with selectedItem'" to populate the second table with chars data. For that you need to add one more item into your model called selectedItem and every time you select or add a row, you point the selectedItem to that elementdata. And use "data-bind='with selecteItem'" for second table.
var ProductViewModel = function(items) {
this.items = ko.observableArray(items);
this.selectedItem = ko.observableArray();
this.itemToAdd = ko.observable("");
this.addItem = function() {
if (this.itemToAdd() != "") {
this.items.push(this.itemToAdd());
this.itemToAdd("");
}
}.bind(this);
};
and on row select call some function selectedItem($data) where $data refers to the current item.
then set that data to selectedItem in model.
function selectedItem(prod){
ProductViewModel.selectedItem(prod);
}
I have a WCF service and and we had to generate a records of clients who have consumed free credit.
I have generated that records but now clients with same login ID's are repeating in the records.
I dnt want to display the login ID again but want to display all the numbers they have called.
Here is the code of my view
#model IEnumerable<MyYello.Admin.Models.CallHistory>
#{ViewBag.Title = "UsersWhoHaveConsumedFreeCredit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Users Who Have Consumed Free Credit</h2>
<table class="table table-striped table-bordered tablesorter" style="display: block">
<thead>
<tr>
<th>Login</th>
<th>FirstName</th>
<th>LastName</th>
<th>Email</th>
<th>Country</th>
<th>Phone</th>
<th>TarrifDesc</th>
<th>CalledNum</th>
<th>CallStart</th>
<th>CallEnd</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Login</td>
<td>#item.FirstName</td>
<td>#item.LastName</td>
<td>#item.Email</td>
<td>#item.Country</td>
<td>#item.Phone</td>
<td>#item.TariffDescription</td>
</tr>
}
#if (!Model.Any())
{
<tr>
<td colspan="14">No Record Found</td>
</tr>
}
</tbody>
</table>
Just need an idea how
You should group by user login first then. Here's an example:
#foreach (var group in Model.GroupBy(history => history.Login))
{
var item = group.First();
<tr>
<td>#item.Login</td>
<td>#item.FirstName</td>
<td>#item.LastName</td>
<td>#item.Email</td>
<td>#item.Country</td>
<td>#string.Join(" - ", group.Select(history => history.Phone))</td>
<td>#item.TariffDescription</td>
</tr>
}