org.apache.click
Interface Control

All Superinterfaces:
Serializable
All Known Subinterfaces:
Container
All Known Implementing Classes:
AbstractContainer, AbstractControl, AbstractLink, ActionButton, ActionLink, Button, Checkbox, Field, FieldSet, FileField, Form, HiddenField, ImageSubmit, Label, PageLink, Panel, PasswordField, Radio, RadioGroup, Reset, Select, Submit, Table, TextArea, TextField

public interface Control
extends Serializable

Provides the interface for Page controls. Controls are also referred to as components or widgets.

When a Page request event is processed Controls may perform server side event processing through their onProcess() method. Controls are generally rendered in a Page by calling their toString() method.

The Control execution sequence is illustrated below:

HTML HEAD Elements

Control HTML HEAD elements can be included in the Page by overriding the getHeadElements() method.

Below is an example of a custom TextField control specifying that the custom.js file should be included in the HTML HEADer:

 public class CustomField extends TextField {

     public List getHeadElements() {
         if(headElements == null) {
             // If headElements is null, create default headElements
             headElements = super.getHeadElements();

             // Add a new JavaScript Import Element for the "/custom.js" script
             headElements.add(new JsImport("/click/custom.js"));
         }
         return headElements;
     }

     ..
 } 

Deploying Resources

The Click framework uses the Velocity Tools WebappResourceLoader for loading templates. This avoids issues associate with using the Velocity ClasspathResourceLoader and FileResourceLoader on J2EE application servers. To make preconfigured resources (templates, JavaScript, stylesheets, etc.) available to web applications Click automatically deploys configured classpath resources to the /click directory at startup (existing files will not be overwritten).

Click supports two ways of deploying pre-configured resources. The recommended deployment strategy (which also the simplest) relies on packaging resources into a special folder of the JAR, called 'META-INF/resources'. At startup time Click will scan this folder for resources and deploy them to the web application. This deployment strategy is the same approach taken by the Servlet 3.0 specification. Please see the section Deploying Custom Resources for more details.

An alternative approach to deploying static resources on startup is provided by the Control interface through the onDeploy(ServletContext) method.

Continuing our example, the CustomField control deploys its custom.js file to the /click directory:

 public class CustomField extends TextField {
     ..

     public void onDeploy(ServletContext servletContext) {
         ClickUtils.deployFile
             (servletContext, "/com/mycorp/control/custom.js", "click");
     }
 } 
Controls using the onDeploy() method must be registered in the application WEB-INF/click.xml for them to be invoked. For example:
 <click-app>
   <pages package="com.mycorp.page" automapping="true"/>

   <controls>
     <control classname="com.mycorp.control.CustomField"/>
   </controls>
 </click-app> 
When the Click application starts up it will deploy any control elements defined in the following files in sequential order: Please note AbstractControl provides a default implementation of the Control interface to make it easier for developers to create their own controls.

See Also:
PageImports

Field Summary
static String CONTROL_MESSAGES
          The global control messages bundle name:   click-control.
 
Method Summary
 Set<Behavior> getBehaviors()
          Returns the list of behaviors for this control.
 Context getContext()
          Deprecated. getContext() is now obsolete on the Control interface, but will still be available on AbstractControl: AbstractControl.getContext()
 List<Element> getHeadElements()
          Return the list of HEAD elements to be included in the page.
 String getId()
          Return HTML element identifier attribute "id" value.
 Map<String,String> getMessages()
          Return the localized messages Map of the Control.
 String getName()
          Return the name of the Control.
 Object getParent()
          Return the parent of the Control.
 boolean hasBehaviors()
          Returns true if this control has any Behaviors registered, false otherwise.
 boolean isAjaxTarget(Context context)
          Returns true if this control is an Ajax target, false otherwise.
 void onDeploy(ServletContext servletContext)
          The on deploy event handler, which provides classes the opportunity to deploy static resources when the Click application is initialized.
 void onDestroy()
          The on destroy request event handler.
 void onInit()
          The on initialize event handler.
 boolean onProcess()
          The on process event handler.
 void onRender()
          The on render event handler.
 void render(HtmlStringBuffer buffer)
          Render the control's HTML representation to the specified buffer.
 void setListener(Object listener, String method)
          Deprecated. this method is now obsolete on the Control interface, but will still be available on AbstractControl: AbstractControl.setListener(java.lang.Object, java.lang.String)
 void setName(String name)
          Set the name of the Control.
 void setParent(Object parent)
          Set the parent of the Control.
 

Field Detail

CONTROL_MESSAGES

static final String CONTROL_MESSAGES
The global control messages bundle name:   click-control.

See Also:
Constant Field Values
Method Detail

getContext

Context getContext()
Deprecated. getContext() is now obsolete on the Control interface, but will still be available on AbstractControl: AbstractControl.getContext()

Return the Page request Context of the Control.

Returns:
the Page request Context

getHeadElements

List<Element> getHeadElements()
Return the list of HEAD elements to be included in the page. Example HEAD elements include JsImport, JsScript, CssImport and CssStyle.

Controls can contribute their own list of HEAD elements by implementing this method.

The recommended approach when implementing this method is to use lazy loading to ensure the HEAD elements are only added once and when needed. For example:

 public MyControl extends AbstractControl {

     public List getHeadElements() {
         // Use lazy loading to ensure the JS is only added the
         // first time this method is called.
         if (headElements == null) {
             // Get the head elements from the super implementation
             headElements = super.getHeadElements();

             // Include the control's external JavaScript resource
             JsImport jsImport = new JsImport("/mycorp/mycontrol/mycontrol.js");
             headElements.add(jsImport);

             // Include the control's external Css resource
             CssImport cssImport = new CssImport("/mycorp/mycontrol/mycontrol.css");
             headElements.add(cssImport);
         }
         return headElements;
     }
 } 
Alternatively one can add the HEAD elements in the Control's constructor:
 public MyControl extends AbstractControl {

     public MyControl() {

         JsImport jsImport = new JsImport("/mycorp/mycontrol/mycontrol.js");
         getHeadElements().add(jsImport);

         CssImport cssImport = new CssImport("/mycorp/mycontrol/mycontrol.css");
         getHeadHeaders().add(cssImport);
     }
 } 
One can also add HEAD elements from event handler methods such as onInit(), onProcess(), onRender() etc.

The order in which JS and CSS files are included will be preserved in the page.

Note: this method must never return null. If no HEAD elements are available this method must return an empty List.

Also note: a common problem when overriding getHeadElements in subclasses is forgetting to call super.getHeadElements. Consider carefully whether you should call super.getHeadElements or not.

Returns:
the list of HEAD elements to be included in the page

getId

String getId()
Return HTML element identifier attribute "id" value. AbstractControl.getId()

Returns:
HTML element identifier attribute "id" value

setListener

void setListener(Object listener,
                 String method)
Deprecated. this method is now obsolete on the Control interface, but will still be available on AbstractControl: AbstractControl.setListener(java.lang.Object, java.lang.String)

Set the controls event listener.

The method signature of the listener is:

An example event listener method would be:

 public boolean onClick() {
     System.out.println("onClick called");
     return true;
 } 

Parameters:
listener - the listener object with the named method to invoke
method - the name of the method to invoke

getMessages

Map<String,String> getMessages()
Return the localized messages Map of the Control.

Returns:
the localized messages Map of the Control

getName

String getName()
Return the name of the Control. Each control name must be unique in the containing Page model or the containing Form.

Returns:
the name of the control

setName

void setName(String name)
Set the name of the Control. Each control name must be unique in the containing Page model or the parent container.

Please note: changing the name of a Control after it has been added to its parent container is undefined. Thus it is best not to change the name of a Control once its been set.

Parameters:
name - of the control
Throws:
IllegalArgumentException - if the name is null

getParent

Object getParent()
Return the parent of the Control.

Returns:
the parent of the Control

setParent

void setParent(Object parent)
Set the parent of the Control.

Parameters:
parent - the parent of the Control

onDeploy

void onDeploy(ServletContext servletContext)
The on deploy event handler, which provides classes the opportunity to deploy static resources when the Click application is initialized.

For example:

 public void onDeploy(ServletContext servletContext) throws IOException {
     ClickUtils.deployFile
         (servletContext, "/com/mycorp/control/custom.js", "click");
 } 
Please note: a common problem when overriding onDeploy in subclasses is forgetting to call super.onDeploy. Consider carefully whether you should call super.onDeploy or not.

Click also supports an alternative deployment strategy which relies on packaging resource (stylesheets, JavaScript, images etc.) following a specific convention. See the section Deploying Custom Resources for further details.

Parameters:
servletContext - the servlet context

onInit

void onInit()
The on initialize event handler. Each control will be initialized before its onProcess() method is called.

Container implementations should recursively invoke the onInit method on each of their child controls ensuring that all controls receive this event.

Please note: a common problem when overriding onInit in subclasses is forgetting to call super.onInit(). Consider carefully whether you should call super.onInit() or not, especially for Containers which by default call onInit on all their child controls as well.


onProcess

boolean onProcess()
The on process event handler. Each control will be processed when the Page is requested.

ClickServlet will process all Page controls in the order they were added to the Page.

Container implementations should recursively invoke the onProcess method on each of their child controls ensuring that all controls receive this event. However when a control onProcess method return false, no other controls onProcess method should be invoked.

When a control is processed it should return true if the Page should continue event processing, or false if no other controls should be processed and the Page.onGet() or Page.onPost() methods should not be invoked.

Please note: a common problem when overriding onProcess in subclasses is forgetting to call super.onProcess(). Consider carefully whether you should call super.onProcess() or not, especially for Containers which by default call onProcess on all their child controls as well.

Returns:
true to continue Page event processing or false otherwise

onRender

void onRender()
The on render event handler. This event handler is invoked prior to the control being rendered, and is useful for providing pre rendering logic.

The on render method is typically used to populate tables performing some database intensive operation. By putting the intensive operations in the on render method they will not be performed if the user navigates away to a different page.

Container implementations should recursively invoke the onRender method on each of their child controls ensuring that all controls receive this event.

Please note: a common problem when overriding onRender in subclasses is forgetting to call super.onRender(). Consider carefully whether you should call super.onRender() or not, especially for Containers which by default call onRender on all their child controls as well.


onDestroy

void onDestroy()
The on destroy request event handler. Control classes should use this method to add any resource clean up code.

This method is guaranteed to be called before the Page object reference goes out of scope and is available for garbage collection.

Container implementations should recursively invoke the onDestroy method on each of their child controls ensuring that all controls receive this event.

Please note: a common problem when overriding onDestroy in subclasses is forgetting to call super.onDestroy(). Consider carefully whether you should call super.onDestroy() or not, especially for Containers which by default call onDestroy on all their child controls as well.


render

void render(HtmlStringBuffer buffer)
Render the control's HTML representation to the specified buffer. The control's Object.toString() method should delegate the rendering to the render method for improved performance.

An example implementation:

 public class Border extends AbstractContainer {

     public String toString() {
         int estimatedSizeOfControl = 100;
         HtmlStringBuffer buffer = new HtmlStringBuffer(estimatedSizeOfControl);
         render(buffer);
         return buffer.toString();
     }

     /**
      * @see Control#render(HtmlStringBuffer)
      */
     public void render(HtmlStringBuffer buffer) {
         buffer.elementStart("div");
         buffer.appendAttribute("name", getName());
         buffer.closeTag();
         buffer.append(getField());
         buffer.elementEnd("div");
     }
 }
 

Parameters:
buffer - the specified buffer to render the control's output to

hasBehaviors

boolean hasBehaviors()
Returns true if this control has any Behaviors registered, false otherwise.

Returns:
true if this control has any Behaviors registered, false otherwise

getBehaviors

Set<Behavior> getBehaviors()
Returns the list of behaviors for this control.

Returns:
the list with this control behaviors.

isAjaxTarget

boolean isAjaxTarget(Context context)
Returns true if this control is an Ajax target, false otherwise.

In order for a Control to be considered as an Ajax target it must be registered through ControlRegistry.registerAjaxTarget.

When the Click handles an Ajax request it iterates the Controls registered with the ControlRegistry and checks if one of them is the Ajax target by calling isAjaxTarget. If isAjaxTarget returns true, Click will process that Control's behaviors.

Please note: there can only be one target control, so the first Control that is identified as the Ajax target will be processed, the other controls will be skipped.

The most common way to check whether a Control is the Ajax target is to check if its ID is available as a request parameter:

 public MyControl extends AbstractControl {

     ...

     public boolean isAjaxTarget(Context context) {
         return context.hasRequestParameter(getId());
     }
 } 
Not every scenario can be covered through an ID attribute though. For example if an ActionLink is rendered multiple times on the same page, it cannot have an ID attribute, as that would lead to duplicate IDs, which isn't allowed by the HTML specification. Control implementations has to cater for how the control will be targeted. In the case of ActionLink it might check against its id, and if that isn't available check against its name.

Parameters:
context - the request context
Returns:
true if this control is an Ajax target, false otherwise