vineri, 6 noiembrie 2015

[OmniFaces utilities 2.2] Update the row of the given UIData component at the given zero-based row index with support for nested UIData

Before reading this post is recommended to read the Update the row of the given UIData component at the given zero-based row index.
You may be also interested in Update the row of the given UIData component at the given zero-based row index in tables with pagination.


[OmniFaces utilities] The updateRow() method updates the row of the given UIData component at the given zero-based row index. This will basically update all direct children of all UIColumn components at the given row index.

Note that the to-be-updated direct child of UIColumn must be a fullworthy JSF UI component which renders a concrete HTML element to the output, so that JS/ajax can update it. So if you have due to design restrictions for example a <h:panelGroup rendered="..."> without an ID, then you should give it an ID. This way it will render a <span id="..."> which is updateable by JS/ajax.

Method:
Usage:

In order to provide an example, we will use PrimeFaces DataTable. More exactly PrimeFaces DataTable with dynamic columns. The columns of DataTable can be created dynamically using the <p:columns> component, as below:

<h:form id="form">
 <p:dataTable id="players" var="player" value="#{playersBean.players}"  binding="#{playersTable}">                   
  <p:columns value="#{playersBean.columns}" var="column">
   <f:facet name="header">
    <h:outputText value="#{column.header}" />
   </f:facet>
   <h:panelGroup id="rowId">
    #{player[column.property]}
   </h:panelGroup>
  </p:columns>
 </p:dataTable>
 ...

Following the PrimeFaces Showcase example, you can easily add a simple input used to specify the columns to display. Moreover, I have added three buttons for updating the data from first two and last row:

 <h:panelGrid columns="6" style="margin:10px 0">
  <p:outputLabel for="template" value="Template:" style="font-weight:bold"/>
  <p:inputText id="template" value="#{playersBean.columnTemplate}" size="50"/>
  <p:commandButton update="players" actionListener="#{playersBean.updateColumns}" value="Update" 
                   process="@parent" icon="ui-icon-refresh"/>             
  <p:commandButton value="Update First Row (OmniFaces)" action="#{playersBean.updateRow(playersTable, 0)}"/>               
  <p:commandButton value="Update Second Row (OmniFaces)" action="#{playersBean.updateRow(playersTable, 1)}"/>               
  <p:commandButton value="Update Last Row (OmniFaces)" action="#{playersBean.updateRow(playersTable, 9)}"/>                
 </h:panelGrid>
</h:form>

You can also use JSF <h:commandButton> nested in <f:ajax>:

<f:ajax>
 <h:commandButton value="Update First Row (OmniFaces)" action="#{playersBean.updateRow(playersTable, 0)}"/>               
 <h:commandButton value="Update Second Row (OmniFaces)" action="#{playersBean.updateRow(playersTable, 1)}"/>               
 <h:commandButton value="Update Last Row (OmniFaces)" action="#{playersBean.updateRow(playersTable, 9)}"/>
</f:ajax>

The PlayersBean is (Player is a simple and intuitive bean):

import org.omnifaces.util.Ajax;
...

@Named
@ViewScoped
public class PlayersBean implements Serializable {

 private final static List<String> VALID_COLUMN_KEYS = Arrays.asList("ranking", "name", "age", "birthplace", "residence", "height", "weight", "coach", "born");
 private String columnTemplate = "ranking name age birthplace residence";
 private List<ColumnModel> columns;
 private List<Player> players = new ArrayList<>();

 private final SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); // not thread-safe, don't use it in production

 public PlayersBean() {
  try {
      // adding 10 players
      players.add(new Player(2, "NOVAK DJOKOVIC", (byte) 26, "Belgrade, Serbia", 
                  "Monte Carlo, Monaco", (short) 188, (byte) 80, "Boris Becker, Marian Vajda", sdf.parse("22.05.1987")));
      ...
      players.add(new Player(9, "RICHARD GASQUET", (byte) 27, "Beziers, France", 
                  "Neuchatel, Switzerland", (short) 185, (byte) 75, "Sergi Bruguera and Sebastien", sdf.parse("18.06.1986")));
      players.add(new Player(3, "DAVID FERRER", (byte) 31, "Javea, Spain", 
                  "Valencia, Spain", (short) 175, (byte) 73, "Jose Francisco Altur", sdf.parse("02.04.1982")));

      createDynamicColumns();
  } catch (ParseException ex) {
           //...
  }
 }

 public void updateColumns() {
  createDynamicColumns();
 }

 private void createDynamicColumns() {
  String[] columnKeys = columnTemplate.split(" ");
  columns = new ArrayList<>();

  for (String columnKey : columnKeys) {
       String key = columnKey.trim();

       if (VALID_COLUMN_KEYS.contains(key)) {
           columns.add(new ColumnModel(columnKey.toUpperCase(), columnKey));
       }
  }
 }

 public void updateRow(UIData table, int index) {
  long seed = System.nanoTime();
  Collections.shuffle(players, new Random(seed));
  Ajax.updateRow(table, index);
 }

 public List<Player> getPlayers() {
  return players;
 }

 public String getColumnTemplate() {
  return columnTemplate;
 }

 public void setColumnTemplate(String columnTemplate) {
  this.columnTemplate = columnTemplate;
 }

 public List<ColumnModel> getColumns() {
  return columns;
 }

 static public class ColumnModel implements Serializable {

  private final String header;
  private final String property;

  public ColumnModel(String header, String property) {
   this.header = header;
   this.property = property;
  }

  public String getHeader() {
   return header;
  }

  public String getProperty() {
   return property;
  }
 }
}

Some outputs:

Before any updates:
After update the first two and last rows:
Remove the age and residence columns and add the height and weight and born columns:
After update the first two and last rows:

Niciun comentariu:

Trimiteți un comentariu