org.apache.click.extras.control
Class FormTable

java.lang.Object
  extended by org.apache.click.control.AbstractControl
      extended by org.apache.click.control.Table
          extended by org.apache.click.extras.control.FormTable
All Implemented Interfaces:
Serializable, Control, Stateful

public class FormTable
extends Table

Provides a FormTable data grid control.

The FormTable is a composite control which includes a form object and an array of FieldColumn objects.

Please note it is possible to associate FormTable with an external Form through this constructor.

FieldColumn extends the Column class and includes a Field object which is uses to render its column value. Each table data cell ≶td> contains a uniquely named form field, which is rendered by the columns field.

When the tables form field data is posted the submitted values are processed by the column field objects using a flyweight style visitor pattern, i.e. the column field instance is reused and processes all the posted values for its column.

After FormTable changes have been submitted their values will be applied to the objects contained in the Tables rows list. If the posted values are invalid for the given field constraints, the field error will be highlighted in the table. Field error messages will be rendered as 'title' attribute tooltip values.

IMPORTANT NOTE

Do not populate the FormTable rowList in the Page's onRender() method.

When using the FormTable control its rowList property must be populated before the control is processed so that any submitted data values can be applied to the rowList objects. This generally means that the FormTable rowList should be populated in the page onInit() method. Note this is different from the Table control where the rowlist is generally populated in the page onRender() method.

FormTable Example

An code example usage of the FormTable is provided below. This example will render the FormTable illustrated in the image above.
 public class FormTablePage extends BorderPage {

     private static final int NUM_ROWS = 5;

     public FormTable table = new FormTable();

     public FormTablePage() {
         // Setup customers table
         table.addStyleClass("simple");
         table.setAttribute("width", "550px");
         table.getForm().setButtonAlign(Form.ALIGN_RIGHT);

         table.addColumn(new Column("id"));

         FieldColumn column = new FieldColumn("name", new TextField());
         column.getField().setRequired(true);
         table.addColumn(column);

         column = new FieldColumn("investments", new InvestmentSelect());
         column.getField().setRequired(true);
         table.addColumn(column);

         column = new FieldColumn("holdings", new NumberField());
         column.setAttribute("style", "{text-align:right;}");
         table.addColumn(column);

         column = new FieldColumn("active", new Checkbox());
         column.setAttribute("style", "{text-align:center;}");
         table.addColumn(column);

         table.getForm().add(new Submit("ok", "   OK   ", this, "onOkClick"));
         table.getForm().add(new Submit("cancel", this, "onCancelClick"));
     }

     public void onInit() {
         // Populate table before it is processed
         List customers = getCustomerService().getCustomersSortedByName(NUM_ROWS);
         table.setRowList(customers);
     }

     public boolean onOkClick() {
         if (table.getForm().isValid()) {
             getDataContext().commitChanges();
         }
         return true;
     }

     public boolean onCancelClick() {
         getDataContext().rollbackChanges();

         List customers = getCustomerService().getCustomersSortedByName(NUM_ROWS);

         table.setRowList(customers);
         table.setRenderSubmittedValues(false);

         return true;
     }
 } 
Note in this example the onCancelClick() button rolls back the changes made to the rowList objects, by reloading their values from the database and having the FormTable not render the submitted values.

Combining Form and FormTable

By default FormTable will create an internal Form to submit its values.

If you would like to integrate FormTable with an externally defined Form, use the constructor which accepts a Form.

Example usage:

 private Form form;
 private FormTable formTable;

 public void onInit() {

     // LIMITATION: Form only processes its children when the Form is submitted.
     // Since FormTable sorting and paging is done via GET requests,
     // the Form onProcess method won't process the FormTable.
     // To fix this we override the default Form#onProcess behavior and check
     // if Form was submitted. If it was not we explicitly process the FormTable.
     form = new Form("form") {
         public boolean onProcess() {
             if (isFormSubmission()) {
                 // Delegate to super implementation
                 return super.onProcess();
             } else {
                 // If form is not submitted, explicitly process the table
                 return formTable.onProcess();
             }
         }
     };

     formTable = new FormTable("formTable", form);
     formTable.setPageSize(10);
     form.add(formTable);
     ...
 } 

See Also:
FieldColumn, Form, Table, Serialized Form

Field Summary
protected  Form form
          The table form.
protected  boolean renderSubmittedValues
          The render the posted form values flag, default value is true.
protected  boolean useInternalForm
          Indicates whether an internal Form should be created, true by default.
 
Fields inherited from class org.apache.click.control.Table
ASCENDING, bannerPosition, caption, CLASS_BLUE1, CLASS_BLUE2, CLASS_COMPLEX, CLASS_ISI, CLASS_ITS, CLASS_MARS, CLASS_NOCOL, CLASS_ORANGE1, CLASS_ORANGE2, CLASS_REPORT, CLASS_SIMPLE, CLASS_STYLES, COLUMN, columnList, columns, controlLink, controlList, dataProvider, height, hoverRows, nullifyRowListOnDestroy, PAGE, pageNumber, pageSize, paginator, PAGINATOR_ATTACHED, PAGINATOR_DETACHED, PAGINATOR_INLINE, paginatorAttachment, POSITION_BOTH, POSITION_BOTTOM, POSITION_TOP, renderId, rowCount, rowList, showBanner, SORT, sortable, sorted, sortedAscending, sortedColumn, width
 
Fields inherited from class org.apache.click.control.AbstractControl
actionListener, attributes, behaviors, headElements, listener, listenerMethod, messages, name, parent, styles
 
Fields inherited from interface org.apache.click.Control
CONTROL_MESSAGES
 
Constructor Summary
FormTable()
          Create a FormTable with no name defined.
FormTable(String name)
          Create a FormTable for the given name.
FormTable(String name, Form form)
          Create an FormTable for the given name and Form.
 
Method Summary
 Column addColumn(Column column)
          Add the column to the table.
 String getButtonsHtml()
          Return the form buttons HTML string representation.
 int getControlSizeEst()
           
 Form getForm()
          Return the form object associated with this FormTable.
 List<Element> getHeadElements()
          Return the HEAD elements for the Control.
 boolean getRenderSubmittedValues()
          Return true if the table will render the submitted form values.
 boolean onProcess()
          Process the FormTable control.
 void render(HtmlStringBuffer buffer)
          Render the HTML representation of the FormTable.
protected  void renderButtons(HtmlStringBuffer buffer)
          Render the Form Buttons to the string buffer.
 void setName(String name)
           
 void setPageNumber(int pageNumber)
           
 void setParent(Object parent)
          Set the parent of the FormTable.
 void setRenderSubmittedValues(boolean render)
          Set whether the table should render the submitted form values.
 void setRowList(List rowList)
          Set the list of form table rows.
 void setSortedAscending(boolean ascending)
           
 void setSortedColumn(String columnName)
           
 
Methods inherited from class org.apache.click.control.Table
add, addControl, addRowAttributes, createRowList, getBannerPosition, getCaption, getColumn, getColumnList, getColumns, getControlLink, getControls, getDataProvider, getFirstRow, getHeight, getHoverRows, getLastRow, getNullifyRowListOnDestroy, getNumberPages, getPageNumber, getPageSize, getPaginator, getPaginatorAttachment, getRenderId, getRowCount, getRowList, getShowBanner, getSortable, getSortedColumn, getState, getTag, getWidth, hasControls, isSorted, isSortedAscending, onDestroy, onInit, onRender, removeColumn, removeColumn, removeColumns, removeState, renderBodyNoRows, renderBodyRowColumns, renderBodyRows, renderFooterRow, renderHeaderRow, renderPaginator, renderPagingControls, renderTableBanner, restoreState, saveState, setBannerPosition, setCaption, setClass, setDataProvider, setHeight, setHoverRows, setNullifyRowListOnDestroy, setPageSize, setPaginator, setPaginatorAttachment, setRenderId, setShowBanner, setSortable, setSorted, setState, setWidth, sortRowList
 
Methods inherited from class org.apache.click.control.AbstractControl
addBehavior, addStyleClass, appendAttributes, dispatchActionEvent, getActionListener, getAttribute, getAttributes, getBehaviors, getContext, getHtmlImports, getId, getMessage, getMessage, getMessages, getName, getPage, getParent, getStyle, getStyles, hasAttribute, hasAttributes, hasBehaviors, hasStyles, isAjaxTarget, onDeploy, removeBehavior, removeStyleClass, renderTagBegin, renderTagEnd, setActionListener, setAttribute, setId, setListener, setStyle, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

form

protected Form form
The table form.


useInternalForm

protected boolean useInternalForm
Indicates whether an internal Form should be created, true by default.


renderSubmittedValues

protected boolean renderSubmittedValues
The render the posted form values flag, default value is true.

Constructor Detail

FormTable

public FormTable(String name,
                 Form form)
Create an FormTable for the given name and Form.

If you want to add the FormTable to an externally defined Form, this is the constructor to use.

Please note: if you want to use FormTable with an external Form, see this example which demonstrates a workaround of the form submit limitation.

Parameters:
name - the table name
form - the table form
Throws:
IllegalArgumentException - if the name is null

FormTable

public FormTable(String name)
Create a FormTable for the given name.

Note that an internal Form control will automatically be created by FormTable.

Parameters:
name - the table name
Throws:
IllegalArgumentException - if the name is null

FormTable

public FormTable()
Create a FormTable with no name defined.

Note that an internal Form control will automatically be created by FormTable.

Please note the control's name must be defined before it is valid.

Method Detail

getButtonsHtml

public String getButtonsHtml()
Return the form buttons HTML string representation.

Returns:
the form buttons HTML string representation

addColumn

public Column addColumn(Column column)
Add the column to the table. The column will be added to the Table.columns Map using its name.

Overrides:
addColumn in class Table
Parameters:
column - the column to add to the table
Returns:
the added column
Throws:
IllegalArgumentException - if the table already contains a column with the same name
See Also:
Table.addColumn(Column)

getForm

public Form getForm()
Return the form object associated with this FormTable.

The returned Form control will either be an internally created Form instance, or an external instance specified through this contructor.

Returns:
the form object

getHeadElements

public List<Element> getHeadElements()
Return the HEAD elements for the Control. This method will include the HEAD elements of the contained fields.

Specified by:
getHeadElements in interface Control
Overrides:
getHeadElements in class Table
Returns:
the list of HEAD elements
See Also:
Control.getHeadElements()

setName

public void setName(String name)
Specified by:
setName in interface Control
Overrides:
setName in class Table
Parameters:
name - of the control
Throws:
IllegalArgumentException - if the name is null
See Also:
Control.setName(String)

setParent

public void setParent(Object parent)
Set the parent of the FormTable. Also set the parent of the Table.getControlLink() to the getForm().

Specified by:
setParent in interface Control
Overrides:
setParent in class Table
Parameters:
parent - the parent of the FormTable
Throws:
IllegalStateException - if AbstractControl.name is not defined
IllegalArgumentException - if the given parent instance is referencing this object: if (parent == this)
See Also:
Control.setParent(Object)

getRenderSubmittedValues

public boolean getRenderSubmittedValues()
Return true if the table will render the submitted form values. By default FormTable renders submitted values.

Returns:
true if the table will render the submitted form values

setRenderSubmittedValues

public void setRenderSubmittedValues(boolean render)
Set whether the table should render the submitted form values.

Parameters:
render - set whether the table should render the submitted form values

setRowList

public void setRowList(List rowList)
Set the list of form table rows. Each row can either be a value object (JavaBean) or an instance of a Map.

Important ensure you set the rowList before control is processed so posted object changes can be applied. Do not invoke this method via the Page onRender() method, otherwise object updates will not be applied.

Please note the rowList is cleared in table Table.onDestroy() method at the end of each request.

Overrides:
setRowList in class Table
Parameters:
rowList - the list of table rows to set

setSortedColumn

public void setSortedColumn(String columnName)
Overrides:
setSortedColumn in class Table
Parameters:
columnName - the name of the sorted column
See Also:
Table.setSortedColumn(java.lang.String)

setSortedAscending

public void setSortedAscending(boolean ascending)
Overrides:
setSortedAscending in class Table
Parameters:
ascending - the ascending sort order status
See Also:
Table.setSortedAscending(boolean)

setPageNumber

public void setPageNumber(int pageNumber)
Overrides:
setPageNumber in class Table
Parameters:
pageNumber - set the currently displayed page number
See Also:
Table.setPageNumber(int)

onProcess

public boolean onProcess()
Process the FormTable control. This method will process the submitted form data applying its values to the objects contained in the Tables rowList.

Specified by:
onProcess in interface Control
Overrides:
onProcess in class Table
Returns:
true if further processing should continue or false otherwise
See Also:
Table.onProcess()

getControlSizeEst

public int getControlSizeEst()
Overrides:
getControlSizeEst in class Table
Returns:
the estimated rendered control size in characters
See Also:
AbstractControl.getControlSizeEst()

render

public void render(HtmlStringBuffer buffer)
Render the HTML representation of the FormTable.

Specified by:
render in interface Control
Overrides:
render in class Table
Parameters:
buffer - the specified buffer to render the control's output to
See Also:
AbstractControl.toString()

renderButtons

protected void renderButtons(HtmlStringBuffer buffer)
Render the Form Buttons to the string buffer.

This method is only invoked if the Form is created by the FormTable, and not when the Form is defined externally.

Parameters:
buffer - the StringBuffer to render to