i'm using primefaces 4.0, JSF Mojarra 2.2.2
and here is my datatable code :
<p:dataTable id="tabexam"
paginatorPosition="bottom"
var="exam"
value="#{dyna.examViewDataModel}"
widgetVar="examTable"
emptyMessage="aucun résultat trouvé pour votre recherche"
paginator="true"
rows="40"
selection="#{dyna.selectedExamen}"
filteredValue="#{dyna.filteredexams}"
selectionMode="single"
resizableColumns="true"
draggableColumns="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="40,80,120">
<p:columns value="#{datatableBean.table}"
var="column"
headerText="#{column.userListname}"
rendered="#{column.visible}"
resizable="#{column.resizable}"
width="#{column.width}"
columnIndexVar="colIndex">
<h:panelGroup>
<p:outputLabel value="#{column.dbname}" styleClass="fonty"/>
</h:panelGroup>
</p:columns>
</p:dataTable>
Here what I've tried so far, but I get empty Strings for getHeaderText in the console and empty width too, i wonder what i'm missing
UIViewRoot view = FacesContext.getCurrentInstance().getViewRoot();
DataTable tabler = (DataTable) view.findComponent(":form1:tabexam");
List<UIColumn> coler = tabler.getColumns();
for (int i = 0; i < coler.size(); i++) {
System.out.println("/////////////////");
System.out.println(coler.get(i).getValueExpression("headerText").getValue(FacesContext.getCurrentInstance().getELContext()));
System.out.println(coler.get(i).getHeaderText());
System.out.println(coler.get(i).isRendered());
System.out.println(coler.get(i).isResizable());
System.out.println(coler.get(i).getWidth());
System.out.println("/////////////////");
}
System.out.println(coler.size());
Note that coler.size()
gives the number of columns shown on the datatable.
but the coler.get(i).getHeaderText()
always gives empty String.
you are mistaking something:
- do not nest
p:column
inside p:columns
DataTable.getColumns does not return what you expect:
public List<UIColumn> getColumns() {
if(columns == null) {
columns = new ArrayList<UIColumn>();
FacesContext context = getFacesContext();
char separator = UINamingContainer.getSeparatorChar(context);
for(UIComponent child : this.getChildren()) {
if(child instanceof Column) {
columns.add((UIColumn) child);
}
else if(child instanceof Columns) {
Columns uiColumns = (Columns) child;
String uiColumnsClientId = uiColumns.getClientId(context);
for(int i=0; i < uiColumns.getRowCount(); i++) {
DynamicColumn dynaColumn = new DynamicColumn(i, uiColumns);
dynaColumn.setColumnKey(uiColumnsClientId + separator + i);
columns.add(dynaColumn);
}
}
}
}
return columns;
}
this returns a synthetic emulation: only columnKey
per column, and, as you stated, the correct number of columns.
generally speaking, p:columns
is ONE component and when you access it from controller layer, you have to refer to its DECLARATION (single component) instead of its REPRESENTATION (multiple columns)
- since you are backing
p:columns
with your #{datatableBean.table}
you should already have all the information you are trying to get from DataTable component, in a reverse-engineered fashion.
update
oh, now i realize what you want to do. you have to use event listeners for that.
from PF showcase:
<p:dataTable var="car" value="#{tableBean.carsSmall}" widgetVar="cars" draggableRows="true">
<p:ajax event="colReorder" listener="#{tableBean.onColReorder}" update=":some:component" />
<p:ajax event="colResize" listener="#{tableBean.onColResize}" update=":some:component"/>
<!-- columns here -->
</p:dataTable>
listening for these events in backing bean and mantain these informations should solve your problem
update 2
whew, it was not simple at all.
due to Primefaces bug for dynamic column resizing (at least for my tries) and incomplete column reordering event implementation, this is what came out:
<h:form id="form">
<h:panelGroup id="model">
<ui:repeat var="column2" value="#{testBean.columnList2}">
<div>#{column2.title} - #{column2.width}</div>
</ui:repeat>
</h:panelGroup>
<p:dataTable var="elem" value="#{testBean.elementList}" resizableColumns="true" draggableColumns="true">
<p:ajax event="colReorder" listener="#{testBean.onColumnReorder}" update=":form:model" />
<p:ajax event="colResize" listener="#{testBean.onColumnResize}" update=":form:model"/>
<c:forEach var="column" items="#{testBean.columnList}">
<p:column headerText="#{column.title}" rendered="#{column.visible}" width="#{column.width}">
<f:attribute name="myCol" value="#{column}"/>
<span>#{elem[column.property]}</span>
</p:column>
</c:forEach>
</p:dataTable>
</h:form>
and this bean:
@ManagedBean
@ViewScoped
public class TestBean implements Serializable
{
private static final long serialVersionUID = 1L;
private List<MyColumn> columnList;
private List<MyColumn> columnList2;
private List<MyElement> elementList;
public class MyColumn
{
private String title;
private String property;
private boolean visible = true;
private boolean resizable = true;
private int width = 100;
public MyColumn(String title, String property, boolean visible, boolean resizable, int width)
{
super();
this.title = title;
this.property = property;
this.visible = visible;
this.resizable = resizable;
this.width = width;
}
// getters and setters
}
public class MyElement
{
private String code;
private String name;
private String type;
public MyElement(String code, String name, String type)
{
super();
this.code = code;
this.name = name;
this.type = type;
}
// getters and setters
}
@PostConstruct
public void init()
{
columnList = new ArrayList<>();
columnList.add(new MyColumn("element code", "code", true, true, 100));
columnList.add(new MyColumn("element name", "name", true, true, 100));
columnList.add(new MyColumn("element type", "type", true, true, 100));
columnList2 = new ArrayList<>(columnList);
elementList = new ArrayList<>();
elementList.add(new MyElement("001", "foo", "normal"));
elementList.add(new MyElement("002", "bar", "strange"));
elementList.add(new MyElement("003", "xyz", "normal"));
elementList.add(new MyElement("004", "abc", "nothing"));
}
public void onColumnResize(ColumnResizeEvent event)
{
UIColumn column = event.getColumn();
int width = event.getWidth();
UIComponent colComponent = (UIComponent) column;
MyColumn myCol = (MyColumn) colComponent.getAttributes().get("myCol");
myCol.setWidth(width);
}
public void onColumnReorder(AjaxBehaviorEvent event)
{
DataTable table = (DataTable) event.getSource();
columnList2.clear();
for(UIColumn column : table.getColumns())
{
UIComponent colComponent = (UIComponent) column;
MyColumn myCol = (MyColumn) colComponent.getAttributes().get("myCol");
columnList2.add(myCol);
}
}
// getters and setters
}
updated code, you can find ordered columns in columnList2
. now are also shown in the form.
now you can use columnList2
to store oreder and widths to db.