The problem I have is the following:
I have a datatable with a list of the class Producto, which internally consists of several fields of simple type and 2 objects of type Proveedor. Categoria and TipoProveedor are enums.
public class Producto {
private int idProducto;
private String nombre;
private Categoria categoria;
private Proveedor proveedorUno;
private Proveedor proveedorDos;
}
public class Proveedor {
private int idProveedor;
private TipoProveedor tipoProveedor;
private String nombre;
private BigDecimal precio;
}
My problem is that in each row of the datatable all the information must be displayed so that if a single filled provider comes, it will be displayed normal but if both fillings come, the part of the provider information is divided into 2 rows. Example:
|------------------------------------------------------------------|
| Nombre | Categoria | idProveedor | Nombre Proveedor | Precio |
|------------------------------------------------------------------|
| DIN-A4 | Papel | 10256 | Proveedor Manolito | 10.59 € |
| | | 24747 | Proveedor Fulanito | 10.75 € |
|------------------------------------------------------------------|
| DIN-A5 | Papel | 10256 | Proveedor Menganito | 4.77 € |
|------------------------------------------------------------------|
| DIN-A3 | Papel | 44787 | Proveedor Saturnino | 14.77 € |
|------------------------------------------------------------------|
I had tried to do it with a datatable like this but it does not look exactly as I need:
<p:dataTable id="listadoProductos" widgetVar="listadoProductos"
value="#{listadoProductosBean.listadoProductos}" var="producto"
emptyMessage="#{messages['tabla.VACIA']}">
<p:column headerText="#{messages['listado.NOMBRE']}">
<h:outputText value="#{producto.nombre}" />
</p:column>
<p:column headerText="#{messages['listado.CATEGORIA']}">
<h:outputText value="#{producto.categoria.desc}" />
</p:column>
<p:column headerText="#{messages['listado.ID_PROVEEDOR']}"
rendered="#{producto.proveedorUno != null && producto.proveedorDos != null}">
<p:panelGrid columns="1">
<p:row>
<h:outputText value="#{producto.proveedorUno.idProveedor}" />
</p:row>
<p:row>
<h:outputText value="#{producto.proveedorDos.idProveedor}" />
</p:row>
</p:panelGrid>
</p:column>
<p:column headerText="#{messages['listado.ID_PROVEEDOR']}"
rendered="#{producto.proveedorUno != null && producto.proveedorDos == null}">
<p:panelGrid columns="1">
<p:row>
<h:outputText value="#{producto.proveedorUno.idProveedor}" />
</p:row>
</p:panelGrid>
</p:column>
<p:column headerText="#{messages['listado.ID_PROVEEDOR']}"
rendered="#{producto.proveedorUno == null && producto.proveedorDos != null}">
<p:panelGrid columns="1">
<p:row>
<h:outputText value="#{producto.proveedorDos.idProveedor}" />
</p:row>
</p:panelGrid>
</p:column>
</p:dataTable>
Is it possible to do what I say?
My version of Primefaces is 6.2 but I could upgrade if I can get what I want.
Many Thanks.
NOTE: it could be worth it (although it is not desired) that the part of the providers divided into 2 appears even if there is only one. Example:
|------------------------------------------------------------------|
| Nombre | Categoria | idProveedor | Nombre Proveedor | precio |
|------------------------------------------------------------------|
| DIN-A4 | Papel | 10256 | Proveedor Manolito | 10.59 € |
| | | 24747 | Proveedor Fulanito | 10.75 € |
|------------------------------------------------------------------|
| DIN-A5 | Papel | 10256 | Proveedor Menganito | 4.77 € |
| | | | | |
|------------------------------------------------------------------|
| DIN-A3 | Papel | 44787 | Proveedor Saturnino | 14.77 € |
| | | | | |
|------------------------------------------------------------------|
You can use the groupRow attribute on the columns you want to group, so:
<p:column headerText="#{messages['listado.NOMBRE']}" groupRow="true">
<h:outputText value="#{producto.nombre}" />
</p:column>
<p:column headerText="#{messages['listado.ID_PROVEEDOR']}">
<h:outputText value="#{producto.proveedorUno.idProveedor}" />
</p:column>
See:
https://www.primefaces.org/showcase/ui/data/datatable/rowGroup.xhtml (rowspan)
https://primefaces.github.io/primefaces/8_0/#/components/datatable?id=row-grouping
To use a fixed row height, give your table a styleClass and style the table cells to have a min-height using CSS.
See:
How do I override default PrimeFaces CSS with custom styles?
Related
I have a DataFrame
+------+--------------------+-----------------+----
| id| titulo |tipo | formacion |
+------+--------------------+-----------------+----
|32084|A | Material | VION00001 TRADE |
|32350|B | Curso | CUS11222 LEADER|
|32362|C | Curso | ITIN9876 EVALUA|
|32347|D | Curso | CUMPLI VION1234 |
|32036|E | Curso | EVAN1111 INFORM|
I need, that into formacion column remove the characters that start with VION|CUS|ITIN|VION|EVAN so Dataframe looks like
+------+--------------------+-----------------+----
| id| titulo |tipo | formacion |
+------+--------------------+-----------------+----
|32084|A | Material | TRADE |
|32350|B | Curso | LEADER |
|32362|C | Curso | EVALUA |
|32347|D | Curso | CUMPLI |
|32036|E | Curso | INFORM |
+------+--------------------+-----------------+----
Thank you for your help
Use split function to split the column by space then get the last element of array.
from Spark2.4+ use element_at function
for Spark < 2.4 use reverse(split(array))[0]
#using element_at
df.withColumn("formacion",element_at(split(col("formacion"),"\\s"),-1)).show()
#or using array_index
df.withColumn("formacion",split(col("formacion"),"\\s")[1]).show()
#split reverse and get first index value
df.withColumn("formacion",reverse(split(col("formacion"),"\\s"))[0]).show()
#+-----+--------------+----------+-------------+
#| id|titulo |tipo | formacion |
#+------+--------------------+-----------------+
#|32084|A | Material | TRADE |
#|32350|B | Curso | LEADER |
#|32362|C | Curso | EVALUA |
#|32347|D | Curso | CUMPLI |
#|32036|E | Curso | INFORM |
#+-----+--------------+----------+-------------+
Sorry guys , this is original Column from DataFrame
formacion = [ VION00001 TRADE, CUS11222 LEADER,ITIN9876 EVALUA ,VION1234 CUMPLI,EVAN11 FR]
This is expected
formacion = [ TRADE, LEADER,EVALUA ,CUMPLI, FR]
I have a Python script that writes to a SQLite3 database and the table is called notify_users, and it has two text-content columns, language_code and username.
Visualized, then, the notify_users database looks like this:
| language_code | username |
---------------------------------
| de | jane_doe |
| sv | jane_doe |
| fi | jane_doe |
| de | tom_petty |
| zh | tom_petty |
What I'd like to do is be able to use two criteria (both the language_code and username) to delete a specific record.
For example, I'd like to delete the record that has both jane_doe in the username column and de in language_code.
| language_code | username |
---------------------------------
| de | jane_doe | X
| sv | jane_doe |
| fi | jane_doe |
| de | tom_petty |
| zh | tom_petty |
How can I format a DELETE FROM notify_users... query appropriately to accomplish this task? Thanks in advance!
You can string together conditions using and:
conn.execute("""delete from notify_user
where language_code = ? and username = ?;""",('de','jane_doe'))
I want to show the data from the database but can not repeat the same profile, just add a location to the existing profile. With the example above becomes clear:
+-------------------+---------------+---------------+
| PROFILE | LOCATION | STATUS |
+-------------------+---------------+---------------+
+-------------------+---------------+---------------+
| Admin | Chief | OK |
+-------------------+---------------+---------------+
| Director | Supervision | OK |
+-------------------+---------------+---------------+
| Secretary | Supervision | OK |
+-------------------+---------------+---------------+
| | Admin | OK |
| | Chief | OK |
| Chief-accessor | Director | OK |
| | Secretary | OK |
| | Supervision | OK |
+-------------------+---------------+---------------+
With this piece of code that is my datatable, I can only repeat them, but I can not group them:
<rich:panel header="User location info" style="margin: 20px 0 !important;">
<h:dataTable id="userLocationList"
value="#{userLocation.list()}" var="row"
styleClass="rich-table"
headerClass="rich-table-subheader rich-table-subheadercell rich-table-thead"
rowClasses="rich-table-row"
columnClasses="rich-table-cell,rich-table-cell,rich-table-cell">
<h:column>
<f:facet name="header">
<h:outputText value="Profile" />
</f:facet>
<center>
<h:outputText value="#{row.profile}" />
</center>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Location" />
</f:facet>
<h:outputText value="#{row.location}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Status" />
</f:facet>
<center>
<h:outputText value="#{row.profile.status ? 'OK' : 'Inactive'}" />
</center>
</h:column>
</h:dataTable>
</rich:panel>
Like this:
+-------------------+---------------+---------------+
| PROFILE | LOCATION | STATUS |
+-------------------+---------------+---------------+
+-------------------+---------------+---------------+
| Admin | Chief | OK |
+-------------------+---------------+---------------+
| Director | Supervision | OK |
+-------------------+---------------+---------------+
| Secretary | Supervision | OK |
+-------------------+---------------+---------------+
| Chief-accessor | Admin | OK |
+-------------------+---------------+---------------+
| Chief-accessor | Chief | OK |
+-------------------+---------------+---------------+
| Chief-accessor | Director | OK |
+-------------------+---------------+---------------+
| Chief-accessor | Secretary | OK |
+-------------------+---------------+---------------+
| Chief-accessor | Supervision | OK |
+-------------------+---------------+---------------+
Method list() from UserLocation is just a select in table_user_location:
select userLoc from UserLocation userLoc where userLoc.user.id = :userId
I've tried to follow some answers here in StackOverflow that say to put a datatable inside another datatable, but as I could was to repeat all locations without group profiles, example:
+-------------------+---------------+---------------+
| PROFILE | LOCATION | STATUS |
+-------------------+---------------+---------------+
+-------------------+---------------+---------------+
| | Chief | |
| | Supervision | |
| | Supervision | |
| | Admin | |
| Admin | Chief | OK |
| | Director | |
| | Secretary | |
| | Supervision | |
+-------------------+---------------+---------------+
| | Chief | |
| | Supervision | |
| | Supervision | |
| | Admin | |
| Director | Chief | OK |
| | Director | |
| | Secretary | |
| | Supervision | |
+-------------------+---------------+---------------+
| | Chief | |
| | Supervision | |
| | Supervision | |
| | Admin | |
| Secretary | Chief | OK |
| | Director | |
| | Secretary | |
| | Supervision | |
+-------------------+---------------+---------------+
| | Chief | |
| | Supervision | |
| | Supervision | |
| | Admin | |
| Chief-accessor | Chief | OK |
| | Director | |
| | Secretary | |
| | Supervision | |
+-------------------+---------------+---------------+
| | Chief | |
| | Supervision | |
| | Supervision | |
| | Admin | |
| Chief-accessor | Chief | OK |
| | Director | |
| | Secretary | |
| | Supervision | |
+-------------------+---------------+---------------+
And so it goes...
My doubt is the generic query I'm doing, so the duplicate content in the table. Does anyone have an idea for this operation?
Questions related:
Nested datatable in JSF 2.0
JSF: Empty nested dataTable
JSF, datatable in datatable
As I was not able to do it the way they return all locations for the same profile and using only one query, I decided to do differently, I thought of using two queries, one for all without repetition profiles (select distinct ...) and one for each location according to the profile. Only realized (correct me if I'm wrong) the property h:datatable renders by columns rather than rows. So, in part, was the first profile column returned all without repeating profiles, however the locations were the same in each cell was shown all user locations without distinction if the cell that the location would appear was of a given profile. That's when I realized I was very focused in locations where the focus was to be on user profiles.
Ran the select distinct the profiles and created a method to return the locations that profiles at the time the table was created. Just as the reported questions, a datatable inside another datatable.
Finally got my code:
<rich:panel header="Informations" style="margin: 20px 0 !important;">
<h:dataTable id="userLocationList"
value="#{userLocation.list()}" var="row"
styleClass="rich-table"
headerClass="rich-table-subheader rich-table-subheadercell rich-table-thead"
rowClasses="rich-table-row"
columnClasses="rich-table-cell,rich-table-cell,rich-table-cell">
<h:column>
<f:facet name="header">
<h:outputText value="Profile" />
</f:facet>
<center>
<h:outputText value="#{row.name}" />
</center>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Localizations" />
</f:facet>
<h:dataTable id="uLoc" var="c"
value="#{home.getLocByProfile(row.idProfile)}">
<h:column>
<h:outputText value="#{c}" />
</h:column>
</h:dataTable>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Status" />
</f:facet>
<center>
<h:outputText value="#{row.active ? 'OK' : 'Inactive'}" />
</center>
</h:column>
</h:dataTable>
</rich:panel>
I have a 2D DataTable which I would like to insert a variable number of panels inside, essentially creating a 3D DataTable.
The 2D table looks as follows:
ll
<p:dataTable var="rowName" value="#{tableBean.rowNames}">
<p:column headerText="" styleClass="ui-widget-header">
<h:outputText value="#{rowName}"/>
</p:column>
<p:columns var="columnName" value="#{tableBean.colNames}" headerText="#{columnName}">
<p:panel>
<h:outputText value="panel"/>
</p:panel>
</p:columns>
</p:dataTable>
And Java:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import java.util.ArrayList;
import java.util.List;
#ManagedBean
#RequestScoped
public class TableBean {
private List<String> rowNames = new ArrayList<String>();
private List<String> colNames = new ArrayList<String>();
private ArrayList<ArrayList<ArrayList<String>>> data3D = new ArrayList<ArrayList<ArrayList<String>>>();
public TableBean() {
rowNames.add("row1");
rowNames.add("row2");
colNames.add("col1");
colNames.add("col2");
colNames.add("col3");
// Setup 3 dimensional structure
for (int i = 0; i < rowNames.size(); i++) {
data3D.add(new ArrayList<ArrayList<String>>());
for (int j = 0; j < colNames.size(); j++) {
data3D.get(i).add(new ArrayList<String>());
}
}
// row 1, col 1, 3 items
data3D.get(0).get(0).add("item1");
data3D.get(0).get(0).add("item2");
data3D.get(0).get(0).add("item3");
// row 1, col 2, 1 items
data3D.get(0).get(1).add("item1");
// row 1, col 3, 2 items
data3D.get(0).get(2).add("item1");
data3D.get(0).get(2).add("item2");
// row 2, col 1, 2 item
data3D.get(1).get(0).add("item1");
data3D.get(1).get(0).add("item2");
// row 2, col 2, 1 item
data3D.get(1).get(1).add("item1");
}
public List<String> getRowNames() { return rowNames; }
public void setRowNames(List<String> rowNames) { this.rowNames = rowNames; }
public List<String> getColNames() { return colNames; }
public void setColNames(List<String> colNames) { this.colNames = colNames; }
public ArrayList<ArrayList<ArrayList<String>>> getData3D() { return data3D; }
public void setData3D(ArrayList<ArrayList<ArrayList<String>>> data3D) { this.data3D = data3D; }
}
But I would like to achieve the following, where p1, p2, p3, etc are PrimeFaces panels:
+------+--------+--------+--------+--
| | Col1 | Col2 | Col3 | .... .... .... ....
+------+--------+--------+--------+--
| | +----+ | +----+ | +----+ |
| | | p1 | | | p1 | | | p1 | |
| | +----+ | +----+ | +----+ |
| Row1 | | p2 | | | | p2 | |
| | +----+ | | +----+ |
| | | p3 | | | |
| | +----+ | | |
+------+--------+--------+--------+
| | +----+ | +----+ | |
| | | p1 | | | p1 | | |
| Row2 | +----+ | +----+ | |
| | | p2 | | | |
| | +----+ | | |
+------+--------+--------+--------+
| .... |
| .... |
....
Is it possible to use the 3rd dimension (list of strings) to create a panel for each string, within each cell of the DataTable?
The solution as RongNK suggested is to use ui:repeat.
By using the brace notation [][], the array from the 3rd dimension can be specified. The index of the row and column can be accessed from the rowIndexVar and colIndexVar attributes from <p:dataTable> and <p:columns> respectively.
<p:dataTable var="rowName" value="#{tableBean.rowNames}" rowIndexVar="rowIdx">
<p:column headerText="" styleClass="ui-widget-header">
<h:outputText value="#{rowName}"/>
</p:column>
<p:columns var="columnName" value="#{tableBean.colNames}" headerText="#{columnName}"
columnIndexVar="colIdx">
<ui:repeat value="#{tableBean.data3D[rowIdx][colIdx]}" var="data">
<p:panel>
<h:outputText value="#{data}"/>
</p:panel>
</ui:repeat>
</p:columns>
</p:dataTable>
Suppose I want display table:
+--------------------------------+
| | | |
----------------------------------
| | |
----------------------------------
| | |
----------------------------------
| | | |
----------------------------------
| | | |
+--------------------------------+
How can I do that with h:panelGrid?
You can't do this with the standard JSF implementation. In JSF 1.2 one would have used Tomahawk's <t:panelGroup colspan="2"> for this. Right now Tomahawk is not officially compatible with JSF 2.0, but I just gave it a try.
<html xmlns:t="http://myfaces.apache.org/tomahawk">
...
<t:panelGrid columns="3">
<t:panelGroup>row1cell1</t:panelGroup>
<t:panelGroup>row1cell2</t:panelGroup>
<t:panelGroup>row1cell3</t:panelGroup>
<t:panelGroup colspan="2">row2cell1-2</t:panelGroup>
<t:panelGroup>row2cell3</t:panelGroup>
<t:panelGroup>row3cell1</t:panelGroup>
<t:panelGroup colspan="2">row3cell2-3</t:panelGroup>
<t:panelGroup>row4cell1</t:panelGroup>
<t:panelGroup>row4cell2</t:panelGroup>
<t:panelGroup>row4cell3</t:panelGroup>
</t:panelGrid>
And it works. I don't guarantee that other Tomahawk components will work as well.
I don't think core JSF supports this, but some 3rd-party implementations might. Someone posted a solution to this using Tomahawk at the end of the post at the following URL:
http://www.coderanch.com/t/211242/JSF/java/colspan