FormBinder Question

Hi,
I am very impressed with the FormBinder. In general I’ve had no problems, but I have run into an issue and I’m not sure if I am doing something stupid (I have some skill at that) or I am using the component wrong.

I have an “automation” base class, that based on the parameters to the parent (base) class will automatically create a CRUD panel, either with a list of values, or just a single form.

The list panel is working fine. I’m working on the single panel and I have hit a strange problem.

First, the structure of the Layout that contains the ViewBoundForm object. I’ve used an XML notation to describe the structure rather than put lots of code.

<verticallayout>
      <horizontallayout>
            <button label="Edit" />
            <button label="Save" visible="false" />
            <button label="Cancel" visible="false" />
      </horizontallayout>
      <viewboundform />
</verticallayout>

The base class handles the button actions so that when “Edit” is clicked, the form is made editable (not readonly) and the Save & Cancel buttons are visible and the Edit button is hidden. All this works fine.

Elsewhere in the application, when the user selects an item from a list in the search function, it automatically updates the form, this is the actual code:

   private void updateDataBinding ()
      {
      Component cmp = tabsheet.getSelectedTab() ;
      
      if (cmp instanceof LazyLoadWrapper)
         cmp = ((LazyLoadWrapper) cmp).getLazyLoadComponent() ;


      if (cmp instanceof Form)   // Not called in this case- but works fine
         {
         Form frm = (Form) cmp ;
         
         if (getCompany() != null)
            frm.setItemDataSource(new BeanItem<Company>(getCompany()) ) ;

         }

      if (cmp instanceof AbstractFormContent)     //FIXME This is where I am having issues displaying the values on the form.
         {
         AbstractFormContent<?> abf = (AbstractFormContent<?>) cmp ;

         if (abf.isListView())
            abf.refresh (getApplication()) ;   // Works fine.
         else
            {
            if (getCompany() != null)
               abf.setItemDataSource(new BeanItem<Company>(getCompany()) ) ;     // The code for this is just below.

            }
         }
      
      }

The user can select a view of data from the tabs, each tab contains an implementation of “AbstractFormComponent” which says whether it has a list and form layout, or just a form. The List portion is working absolutely fine.

In the “AbstractFormComponent” the “setItemDataSource” method looks like this:

   public void setItemDataSource(BeanItem<?> beanItem)
      {
      if (null != form)
         {
         if (! form.isImmediate())
            form.setImmediate(true) ;
         
         if (form instanceof ViewBoundForm)
            {
            ((ViewBoundForm) form).setItemDataSource(beanItem) ;
            System.out.printf("Obj: %s | Prop: %s%n", ((Company)beanItem.getBean()).getName(), beanItem.getItemProperty("name"));
            }
         else
            form.setItemDataSource(beanItem) ;
         }

      }

The System.out.printf line prints out the correct values, but the form does not display the values in the components (the form itself displays fine). At first, I just use the internal “form” variable which is of type “Form”. I later added the instanceof and cast, just in case ViewBoundForm was having issues because the inner form.setItemDataSource might be being called.

So the datasource is 100% certain being set correctly. Yet, the form does not display the values. I’ve even made the containing layout immediate, just in case that was the problem, but it makes no difference.

All suggestions welcome.

I think I’ve found the answer. It seems that FormBinder cannot process a class that does not inherit directly from CustomComponent. I have an intermediary class that adds buttons and stuff and takes a generics parameter.

This approach does not appear to work with FormBinder.

As soon as I changed the class back to a plain CustomComponent, it works.

I’d welcome some comments from the component author to confirm my findings.
Thanks in advance.

The final answer is that you cannot do something like this:

<verticallayout>
       <horizontallayout>
          .. buttons, such as Add, Edit, etc. ...
       </horizontallayout>
       <gridlayout>
          ... components you want FormBinder to bind
       </gridlayout>
 </verticallayout>

Once you move the buttons into the footer of the form, with setFooter(…), then everything works OK.

Still, would wlecome comments from the addon author.