click-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bob Schellink <sab...@gmail.com>
Subject Renderable property
Date Tue, 15 Dec 2009 06:17:23 GMT
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

Mime
View raw message