You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@click.apache.org by Bob Schellink <sa...@gmail.com> on 2009/12/15 07:17:23 UTC

Renderable property

Hi all,

One of the areas where Click can be confusing is when dynamically creating/adding controls to a Page 
or container. The problem is quite apparent when trying to create and add controls from within a 
control's action event. Since Click has a predefined event flow (onInit, onProcess, onRender), this 
can easily lead to the new control being instantiated after crucial events have fired, such as 
onInit, onProcess etc. A simple workaround is to manually fire these events upon creation eg:

   control.onInit();

But this isn't obvious for new users. I normally suggest that all controls be created up front so 
they participate in the full event flow. Then instead of adding the controls one can remove the ones 
not needed at that time.

However this doesn't feel natural and creates more problems when working with stateful pages, since 
the controls have to be re-added.

So how about we add a new Control method (isRenderable/setRenderable or isVisible/setVisible) which 
controls whether the Control is rendered or not. Thus all controls can be created/added at design 
time and partake in all Click events, but their rendered state is controlled at runtime.

Expected usage:

public MyPage extends Page {

   private Form form;

   public MyPage() {
     form = new Form("form");

     form.add(new TextField("name") {
       public boolean isRenderable() {
         return isCompany();
       }
     });

     form.add(new TextField("firstname") {
       public boolean isRenderable() {
         return !isCompany();
       }
     });

     form.add(new TextField("lastname") {
       public boolean isRenderable() {
         return !isCompany();
       }
     });
   }

   private boolean isCompany() {
     Object entity = mydao.load(Entity.class, "123");
     if (entity instanceof Company) {
       return true;
     } else {
       return false;
     }
   }
}

In the example above we either render the "name" field or firstname+lastname fields depending on 
whether the domain entity is a Company or a Person.

The isRenderable property can be used by the Control and/or Container to determine if it should be 
drawn. getHeadElements implementations can also check this property whether to include JS/CSS:

public MyControl extends AbstractControl {

   public void render(HtmlStringBuffer buffer) {
     if (!isRenderable()) {
       return;
     }
     ...
   }

   public List getHeadElements() {
     if (!isRenderable()) {
       return new ArrayList(0);
     }
     ...
   }
}

The property can also be used in Velocity templates:

#if($form.isRenderable())
   $form
#end


Good idea/bad idea? What do you think?

kind regards

bob