Resizing, reordering, and toggling columns in dataTable

The dataTable component offers enhanced features on its content, such as resizing of columns, reordering of rows and columns via drag and drop, and toggling of columns for visibility.

How to do it…

Resizing should be enabled by setting the resizableColumns attribute to true, as shown here:

<p:dataTable id="resizing" var="car" value="#{dataTableBean.cars}"
  resizableColumns="true">
  <p:column headerText="Year">
    <h:outputText value="#{car.year}" />
  </p:column>
  <p:column headerText="Name">
    <h:outputText value="#{car.name}" />
  </p:column>
</p:dataTable>

Note

After resizing, the state of the columns is preserved on the postback of a page via cookie-based persistence.

Reordering of rows and columns is possible with the draggableRows and draggableColumns attributes respectively. A sample definition is given here:

<p:dataTable value="#{dataTableBean.cars}" var="car"
  draggableRows="true" draggableColumns="true">
  ...
</p:dataTable>

While performing reordering, the user is assisted with placeholders, as seen in this image:

How to do it…

Row toggling is supported by dataTable with the help of the <p:rowToggler> and <p:rowExpansion> components. The rowToggler component renders an expanding/toggling icon when placed in a column, and rowExpansion defines the content that will be displayed beneath the expanded row. An AJAX call is made with the expansion. The definition of the table will be as follows:

<p:dataTable id="rowToggle" var="car"
  value="#{dataTableBean.cars}">
  <p:column style="width: 20px">
    <p:rowToggler />
  </p:column>
  <p:column headerText="Year">
    <h:outputText value="#{car.year}" />
  </p:column>
  <p:column headerText="Name">
    <h:outputText value="#{car.name}" />
  </p:column>

  <p:rowExpansion>
    <h:panelGrid id="display" columns="2" cellpadding="4">
      <f:facet name="header">
        <p:graphicImage
          value="/resources/images/autocomplete/#{car.name}.png"
          width="60" height="40" />
      </f:facet>

      <h:outputText value="Name:" />
      <h:outputText value="#{car.name}" />

      <h:outputText value="Year:" />
      <h:outputText value="#{car.year}" />
    </h:panelGrid>
  </p:rowExpansion>
</p:dataTable>

The visual output of the table with the first row expanded will be as follows:

How to do it…

The expandedRow attribute of dataTable with its value set to true, defines whether all the rows of the table should be expanded by default. The rowExpandMode attribute with the value single defines only whether one row should be expanded at a time. When set to multiple, which is the default value, the expanded row will not be collapsed when a second row gets expanded.

There's more…

By default, while resizing a column by dragging it to the left-hand side or the right-hand side, a helper column line is rendered to state the possible final position of the column's line. If you want to resize the column in live mode without this helper, you can set liveResize to true to see it in action instantly.

AJAX behavior events on resize

The dataTable component provides the colResize AJAX behavior event that will be fired when a column is resized:

<p:dataTable id="resizingAJAX" var="car"
  value="#{dataTableBean.cars}" resizableColumns="true">
  <p:ajax event="colResize" listener="#{dataTableBean.onResize}"
    update=":mainForm:growl" />
</p:dataTable>

The onResize method will be invoked with an instance of org.primefaces.event.ColumnResizeEvent. The width and height of the resized column can be retrieved from the event instance. The definition for the onResize method is given here:

public void onResize(ColumnResizeEvent event) {
  MessageUtil.addInfoMessage("column.resized",
    "W:" + event.getWidth() + " - H:" + event.getHeight());
}

AJAX behavior events on row and column reordering

The dataTable component provides the rowReorder AJAX behavior event that will be fired when a row is repositioned by dragging and dropping:

<p:dataTable id="reorderingAJAX" var="car"
  value="#{dataTableBean.cars}" draggableRows="true">
  <p:ajax event="rowReorder" update=":mainForm:growl" 
    listener="#{dataTableBean.onRowReorder}" />
  ...
</p:dataTable>

The onRowReorder method will be invoked with an instance of org.primefaces.event.ReorderEvent. The start and end indices for the column that is repositioned can be retrieved from the event. The definition for the onReorder method is given here:

public void onRowReorder(ReorderEvent event) {
  MessageUtil.addInfoMessage("row.reordered", "From:" +
    event.getFromIndex() + " - To:" + event.getToIndex());
}

The dataTable component also provides the colReorder AJAX behavior event that will be fired when a column is repositioned by dragging and dropping. The column reorder doesn't support ReorderEvent with the listener method at the moment; AjaxBehaviorEvent should be used instead.

Toggling columns

With the <p:columnToggler> helper component, it's possible to toggle the visible columns of the table. Here's how column toggling is used:

<p:dataTable id="colToggle" var="car"
  value="#{dataTableBean.cars}">
  <f:facet name="header">
    <p:commandButton id="toggler" type="button" 
      value="Columns" />
    <p:columnToggler datasource="colToggle" 
      trigger="toggler" />
  </f:facet>
  <p:column headerText="Year">
    <h:outputText value="#{car.year}" />
  </p:column>
  <p:column headerText="Name">
    <h:outputText value="#{car.name}" />
  </p:column>
</p:dataTable>

The id parameter of the table should be provided to the datasource attribute of columnToggler. With the trigger attribute, columnToggler attaches itself to a button where a list of all the columns will be rendered, along with a checkbox. By default, all the header text values are rendered in the UI. So, if you do not want a column to be on that list for toggling, you can set the toggleable attribute of that column to false.

Note

It's advised that you do not use scrollable feature in a table that uses columnToggler since they are not fully compatible.

The visual output of columnToggler inside the header of the table is shown here:

Toggling columns

AJAX behavior event on column toggling

The columnToggler component offers the toggle AJAX behavior event that will be fired when a column is toggled:

<p:dataTable id="colToggleAJAX" var="car"
  value="#{dataTableBean.cars}">
  <f:facet name="header">
    <p:commandButton id="togglerAJAX" type="button"
      value="Columns" />
    <p:columnToggler datasource="colToggleAJAX" 
      trigger="togglerAJAX">
      <p:ajax event="toggle" update=":mainForm:growl"
        listener="#{dataTableBean.onColumnToggle}" />
    </p:columnToggler>
  </f:facet>
  ...
</p:dataTable>

The onColumnToggle method will be invoked with an instance of org.primefaces.event.ToggleEvent. The visibility of the column can be retrieved from the event as enum. The definition for the onColumnToggle method is given here:

public void onColumnToggle(ToggleEvent e) {
  MessageUtil.addInfoMessage("col.toggled",
    "Visibility:" + e.getVisibility());
}

Adding state for column toggling

By default, columnToggler is stateless. While doing sorting and filtering on columns of a table where they are toggled, synchronization issues might occur, and this is because those columns will come right back in after filtering or sorting.

To make column toggling with sorting or filtering work, we will set the visible attribute of columns by binding them to a list from the backing bean here:

<p:dataTable id="colToggleAJAX" var="car"
  value="#{dataTableBean.cars}">
  <f:facet name="header">
    <p:commandButton id="togglerAJAX" type="button"
      value="Columns" />
    <p:columnToggler datasource="colToggleAJAX" 
      trigger="togglerAJAX">
      <p:ajax event="toggle" update=":mainForm:growl"
        listener="#{dataTableBean.onColumnToggle}" />
    </p:columnToggler>
  </f:facet>
  <p:column headerText="Year"
    visible="#{dataTableBean.visibleList[0]}">
    <h:outputText value="#{car.year}" />
  </p:column>
  <p:column headerText="Name"
    visible="#{dataTableBean.visibleList[1]}">
    <h:outputText value="#{car.name}" />
  </p:column>
</p:dataTable>

The definition of the visible list and the onColumnToggle method on the backing bean is shown here:

private List<Boolean> visibleList;

public void onColumnToggle(ToggleEvent e) {
  visibleList.set((Integer) e.getData(),
    e.getVisibility() == Visibility.VISIBLE);
}

PrimeFaces Cookbook Showcase application

This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on application severs compatible with Servlet 3.x, such as JBoss WildFly and Apache TomEE.

The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter5/dataTableResizeReorderToggle.jsf.

See also

For details about the MessageUtil class, see the Internationalization (i18n) and Localization (L10n) recipe in Chapter 1, Getting Started with PrimeFaces.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.189.186