--- title: Automatic Form Generation order: 8 layout: page --- [[jpacontainer.fieldfactory]] = Automatic Form Generation The JPAContainer [classname]#FieldFactory# is an implementation of the [interfacename]#FormFieldFactory# and [interfacename]#TableFieldFactory# interfaces that can generate fields based on JPA annotations in a POJO. It goes further than the [classname]#DefaultFieldFactory#, which only creates simple fields for the basic data types. This way, you can easily create forms to input entities or enable editing in tables. The generated defaults are as follows: [options="header"] |=============== |Annotation|Class Mapping |[literal]#++@ManyToOne++#|[classname]#NativeSelect# |[literal]#++@OneToOne++#, [literal]#++@Embedded++#|Nested [classname]#Form# |[literal]#++@OneToMany++#, [literal]#++@ElementCollection++#|[classname]#MasterDetailEditor# (see below) |[literal]#++@ManyToMany++#|Selectable [classname]#Table# |=============== The field factory is recursive, so that you can edit a complex object tree with one form. [[jpacontainer.fieldfactory.configuring]] == Configuring the Field Factory The [classname]#FieldFactory# is highly configurable with various configuration settings and by extending. // You need to make the configuration before ... The [methodname]#setMultiSelectType()# and [methodname]#setSingleSelectType()# allow you to specify a selection component that is used instead of the default for a field with [literal]#++@ManyToMany++# and [literal]#++@ManyToOne++# annotation, respectively. The first parameter is the class type of the field, and the second parameter is the class type of a selection component. It must be a sub-class of [classname]#AbstractSelect#. The [methodname]#setVisibleProperties()# controls which properties (fields) are visible in generated forms, subforms, and tables. The first paramater is the class type for which the setting should be made, followed by the IDs of the visible properties. The configuration should be done before binding the form to a data source as that is when the field generation is done. Further configuration must be done by extending the many protected methods. Please see the API documentation for the complete list. [[jpacontainer.fieldfactory.using]] == Using the Field Factory The most basic use case for the JPAContainer [classname]#FieldFactory# is with a [classname]#Form# bound to a container item: ---- // Have a persistent container final JPAContainer countries = JPAContainerFactory.make(Country.class, "book-examples"); // For selecting an item to edit final ComboBox countrySelect = new ComboBox("Select a Country", countries); countrySelect.setItemCaptionMode(Select.ITEM_CAPTION_MODE_PROPERTY); countrySelect.setItemCaptionPropertyId("name"); // Country Editor final Form countryForm = new Form(); countryForm.setCaption("Country Editor"); countryForm.addStyleName("bordered"); // Custom style countryForm.setWidth("420px"); countryForm.setBuffered(true); countryForm.setEnabled(false); // When an item is selected from the list... countrySelect.addValueChangeListener(new ValueChangeListener(){ @Override public void valueChange(ValueChangeEvent event) { // Get the item to edit in the form Item countryItem = countries.getItem(event.getProperty().getValue()); // Use a JPAContainer field factory // - no configuration is needed here final FieldFactory fieldFactory = new FieldFactory(); countryForm.setFormFieldFactory(fieldFactory); // Edit the item in the form countryForm.setItemDataSource(countryItem); countryForm.setEnabled(true); // Handle saves on the form final Button save = new Button("Save"); countryForm.getFooter().removeAllComponents(); countryForm.getFooter().addComponent(save); save.addClickListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { try { countryForm.commit(); countryForm.setEnabled(false); } catch (InvalidValueException e) { } } }); } }); countrySelect.setImmediate(true); countrySelect.setNullSelectionAllowed(false); ---- See the http://demo.vaadin.com/book-examples-vaadin7/book#jpacontainer.fieldfactory.formonetoone[on-line example, window="_blank"]. This would create a form shown in <>. [[figure.jpacontainer.fieldfactory.using]] .Using FieldFactory with One-to-Many Relationship image::img/fieldfactory-form.png[] If you use Hibernate, you also need to pass an [classname]#EntityManagerPerRequestHelper#, either for the constructor or with [methodname]#setEntityManagerPerRequestHelper()# ifdef::web[] , as described in <> endif::web[] . [[jpacontainer.fieldfactory.masterdetaileditor]] == Master-Detail Editor The [classname]#MasterDetailEditor# is a field component that allows editing an item property that has one-to-many relationship. The item can be a row in a table or bound to a form. It displays the referenced collection as an editable [classname]#Table# and allows adding and removing items in it. You can use the [classname]#MasterDetailEditor# manually, or perhaps more commonly use a JPAContainer [classname]#FieldFactory# to create it automatically. As shown in the example in <>, the factory creates a [classname]#MasterDetailEditor# for all properties with a [literal]#++@OneToMany++# or an [literal]#++@ElementCollection++# annotation.