Reputation: 381
I've got a datatable along with sort, filter and columntoggler. Firstly, when I select and unselect a column in the same page everything is fine.
As you can see, my first column has disappeared
My problem here is when I go to the next page with pagination tool and if I want to unselect a column, it displays only the column header and not their rows as you can see below : The initial hidden column is now displayed but we've got a gap. The last column is right now empty and the first one take the value to the second column.
This is my datatable structure :
<p:dataTable id="datatable" var="mon" value="#{X.resultQuery}"
first="#{dataTableController.first}"
resizableColumns="true"
rows="20"
paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="30,40,50"
draggableColumns="true"
paginatorPosition="bottom"
selectionMode="single" rowKey="#{mon[4]}"
>
<f:facet name="header">
<p:commandButton id="toggler" type="button" value="Hide Columns" icon="ui-icon-calculator" />
<p:columnToggler datasource="datatable" trigger="toggler">
<p:ajax event="toggle" listener="#{columnTogglerController.onToggle}" />
</p:columnToggler>
</f:facet>
This is my ColumnTogglerController :
public class ColumnTogglerController implements Serializable {
private List<Boolean> list;
/**
* Creates a new instance of ColumnTogglerController
*/
public ColumnTogglerController() {
}
public List<Boolean> getList() {
return list;
}
public void setList(List<Boolean> list) {
this.list = list;
}
@PostConstruct
public void init() {
setList(Arrays.asList(true, true, true, true, true, true, true, true, true, true, true));
}
public void onToggle(ToggleEvent e) {
list.set((Integer) e.getData(), e.getVisibility() == Visibility.VISIBLE);
}
}
Basically my program is based on this blog : http://blog.primefaces.org/?p=3341
Thanks for you help.
Upvotes: 3
Views: 4016
Reputation: 300
I happen to encounter this recently. The blog actually works. The problem is draggableColumns="true"
makes the index of columns change. So, instead of list I used 2 maps:
private final Map<String, Boolean> colVisibilityMap = new HashMap<>();
private final Map<Integer, String> colIndexMap = new HashMap<>();
During initialization, I set the colIndexMap and the colVisibilityMap (and I used the id/clientId as the key). On column reorder, I update the colIndexMap. And on toggle, I update the colVisibilityMap base on colIndexMap.
public Map<String, Boolean> getColVisibilityMap() {
return Collections.unmodifiableMap(colVisibilityMap);
}
private String getColumnId(String fullId) {
String[] idParts = fullId.split(":");
return idParts[idParts.length - 1];
}
@PostConstruct
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
DataTable table = (DataTable) context.getViewRoot().findComponent(":form:tableid");
List<UIColumn> columns = table.getColumns();
for (int i = 0; i < columns.size(); i++) {
final String columnId = this.getColumnId(columns.get(i).getClientId());
colIndexMap.put(i, columnId);
colVisibilityMap.put(columnId, true);
});
}
public void onColumnReorder(AjaxBehaviorEvent e) {
List<UIColumn> columns = ((DataTable) e.getSource()).getColumns();
for (int i = 0; i < columns.size(); i++) {
this.colIndexMap.put(i, this.getColumnId(columns.get(i).getClientId()));
}
}
public void onToggle(ToggleEvent e) {
// If we use list here, e.getData() may not be the correct index due to column reordering.
this.colVisibilityMap.put(this.colIndexMap.get((Integer) e.getData()), e.getVisibility() == Visibility.VISIBLE);
}
Here is the code on my JSF page:
<p:dataTable id="tableid" widgetVar="tableWidgetVar" draggableColumns="true" paginator="true"
<!-- ommitted other attributes -->
>
<p:ajax event="colReorder" listener="#{bean.onColumnReorder}"/>
<f:facet name="header">
<p:commandButton id="toggler" type="button" value="Columns"/>
<p:columnToggler datasource="tableid" trigger="toggler">
<p:ajax event="toggle" listener="#{bean.onToggle}"/>
</p:columnToggler>
</f:facet>
<p:column id="col1" visible="#{bean.colVisibilityMap['col1']}">
<!-- ommitted -->
</p:column>
<p:column id="col2" visible="#{bean.colVisibilityMap['col2']}">
<!-- ommitted -->
</p:column>
<!-- and so on... -->
</p:dataTable>
Upvotes: 3