FieldBinder Add-on — an extended FieldGroup with Master/Detail support

Our Special Xmas Gift to the Vaadin Community: the

FieldBinder Add-on

!

An advanced FieldGroup implementation with support for automated generation of Master/Detail forms in a very few lines of code, easily extensible through Vaadin’s Event Listener mechanism.


What is wrong with Good Ol’ FieldGroup?

Vaadin’s FieldGroup and BeanFieldGroup are non-visual components that build and automatically bind Fields to a data source. The data source may be an Item or a Java Bean. However, FieldGroups have quite a few limitations:

  • A FieldGroup only contains bound fields
  • If a field is not bound to a datasource (using unbind()), then it is automatically removed from the FieldGroup. The FieldGroup is then unaware that the field exists. Trying togetField() returns null.
  • A FieldGroup cannot buildAndBind() fields with unrecognized values, but it is extensible through a Factory; however, unrecognized values include Collection types, such as Lists, which are typical of forms of the Master/Detail-type
  • There is no generic implementation of a standard Master/Detail editor (the JPAContainer MasterDetailEditorimplementation is ad-hoc)
  • There is no way to bind a FieldGroup to a Container: a FieldGroup is bound to an Item. Thus, there is no simple way to scan through a collection of records and display their contents in a form


Meet the FieldBinder

The FieldBinder add-on is an advanced FieldGroup implementation.

Features:

  • A FieldBinder binds to a Java Bean, like a BeanFieldGroup
  • Managed Fields (built using build()) can be always bind()‘ed and unbind()'ed; the FieldBinder will always keep track of them
  • A FieldBinder can build() and bind() a component that displays a bean property even when it is a List
  • A FieldBinder can be bound to a Container. The DataNavigation interface provides commands to move an internal pointer to the next, previous, first and last Item in the Container (the Container must implementContainer.Ordered: most Container implementations do, since it is required by Table)
  • The DataNavigation interface provides commands to scan through a dataset and retrieving the Item that it points to.
  • The DataNavigation interface provides standard behavior for performing CRUD operations (and, experimentally, lookup operations), which can be extended through a regular, Vaadin-style listener mechanism
  • FieldBinder comes with standard built-in CRUD for the ListContainer and the Lazy Mongo Container. The ListContainer should already cover most Java Bean use-cases, including JPA. Support for the Vaadin’s official JPAContainer is under development.
  • The ButtonBar component (and its relatives, NavButtonBar, CrudButtonBar, FindButtonBar) may be bound to a DataNavigation and automatically generate buttons for user interactions (automatic shortcut key bindings will come soon!)
  • ButtonBars are i18n compliant through the standard Java ResourceBundle mechanism
  • The ListTable and BeanTable wrappers augment Vaadin’s regular Table with default behavior for basic CRUD.

You can find it on the

Vaadin Addon Directory

, please play with it and let us know what you think!

Feature and Pull Requests are welcome on our
GitHub
repositories:

Great. This looks really interesting, master/detail would be much easier this way.
But I’m desperatly waiting for support of JPAContainer, otherwise it would not help much.
Is there a timeline for this?

Thank you for your work!

Hi,

sorry for the late reply, we’ve been working on the JPA implementation, and we’re glad to let you know that experimental support for the JPAContainer has landed in
FieldBinder v1.1 !
Please feel free to take a look and play with it. The instructions from the website have not changed! Report any issue on

GitHub


CHANGELOG v1.1

  • Added experimental support for JPA Container
  • Ported to Viritin (new name for Maddon)

We are glad to announce
Version 1.2
of the
FieldBinder Add-on.

The new version introduces
Zoom and DrillDown Fields,
and experimental
Vaadin Grid
support (through the built-in extension
FilterableGrid
) ! Among technical improvements, the
built-in event handlers
were streamlined and reorganized to be easier to understand and use, and the new
Search Fields
provide an easier way to write
Search Patterns
. Finally,
filter generation
has been further improved.

Go fetch the latest and greatest version from

Vaadin Addon Directory

, take your time to review the

code on GitHub

and the

full reference documentation

. And, for a sneak peek, we have uploaded a

new, slick online demo on Heroku

(full source code on GitHub as well).

This is awesome…i was developing a fairly similar thing but then had to leave it behind because had no time.
When JPAContainer and Grid full support is complete this will be one of the most valuable add-on for business applications.
Just one suggestion: i know there is a getTable() where do it, but a way to define which column to show direcly on master-detail list generation whould be awesome. Even a “.withColumns(…)”, it would fit so much your overall boilerplate-cut style :wink:

Also I would be interested in getting involved in the development. As I said it could really be an asset for the overall vaadin framework and i would partecipate glady, since i’m planning on use this quite extensively for me and my firm!

MUST-EDIT: i have also to say kudos because you wrote it in a very well done object-oriented extension-friendly way, and so far i had ZERO issues implementing some variation, like custom buttons, because every action can be accessed (there are even listeners): this is not commonly seens and the main reason i often end up “reinvent the wheel myself”. Grats!

We have just released
version 1.3
with
substantial improvements
in the way
tables
are handled.
In this re-designed architecture, you are now able to
declare
Fields in a table
statically
and attach events to them, bringing the same ease of use that we have in
Grid
to traditional
Table
!



Changes with respect to traditional TableFieldFactory.

Consider an
Address(country, city)
entity. Suppose you want to show a ComboBox for countries and a ComboBox for cities. With the Table, you would write:

myTable.setTableFieldFactory(new TableFieldFactory() {
  @Override
  public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) {
    if (itemId != fieldBinder.getNavigation().getCurrentItemId()) return null;
    if ("country".equals(propertyId)) {
      Field<?> country = ... ;
      return country;
    }
    if ("city".equals(propertyId)) {
      Field<?> city = ... ;
      return city;
    }
    ...
  }
});

The downside of which is that you cannot statically refer to Fields in your regular code. With
FieldBinder 1.3
you are now able to define fields using the
FieldBinder.build()
method, just like you would do for non-tabular forms. For instance, suppose that you want to attach events to the
country
and
city
fields, such as filling a
city
combobox when some
country
is selected; suppose the
Address
is inside a
ListTable
declared as such (see our
Extended Tutorial
):

final ListTable<Address> addressList =
      binder.buildListOf(Address.class, "addressList");

You can get the internal FieldBinder instance of the ListTable with:

final FieldBinder<Address> addressListBinder = addressList.getFieldBinder()

You may then declare fields:

final TextField street = addressListBinder.build("street"), zipCode = addressListBinder.build("zipCode"); // let us specify that we want ComboBoxes here: final ComboBox country = addressListBinder.build("Country", "country", ComboBox.class); final ComboBox city = addressListBinder.build("City", "city", ComboBox.class); …and attach event listeners as usual!

// add event listeners to the country field
country.addItems(Arrays.asList("England", "Scotland", "Wales", "Northern Ireland"));
country.addValueChangeListener(event -> {
  city.removeAllItems();
  if ("England".equals(event.getProperty().getValue())) {
     city.addItems(Arrays.asList("London", "Liverpool", "Oxford"));
     city.select("London");
  }
});

// You can also refer to Table fields within navigation event listeners:
addressList.getNavigation().addOnCommitListener(event ->
  Notification.show("The street was: "+street.getValue());
);

Among other changes in this release are several bug fixes, and built-in support for ResourceBundles. You can now use the
FieldBinder.withResourceBundle(resbundle)
method to specify mappings between property ids and localized captions!
For an example, see the documentation site
, and the
demo source code
.
The live demo is also online
(see Tutorial 3)

Progress has also been made with respect to Grid support (
FieldBinder.withGridSupport()
) but it is still experimental at this stage.

Let us know what you think!

Version
1.4
is out with a heap of refactoring a bug fixes! Don’t forget to

checkout the extended documentation
!

Will your component work with Vaadin 8?

I am trying to resolve this issue:


https://vaadin.com/forum#!/thread/15765871