From: Erik Lumme Date: Fri, 15 Sep 2017 10:08:23 +0000 (+0300) Subject: Migrate CreatingACustomFieldFOrEditingTheAddressOfAPerson X-Git-Tag: 7.7.11~6^2~12 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5a8679c8dc667000086d79d586639bcb43af88ad;p=vaadin-framework.git Migrate CreatingACustomFieldFOrEditingTheAddressOfAPerson --- diff --git a/documentation/articles/CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc b/documentation/articles/CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc new file mode 100644 index 0000000000..a28b63150f --- /dev/null +++ b/documentation/articles/CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc @@ -0,0 +1,266 @@ +[[creating-a-customfield-for-editing-the-address-of-a-person]] +Creating a CustomField for editing the address of a person +---------------------------------------------------------- + +A normal use case is that you want to create a form out a bean that the +user can edit. Often these beans contain references to other beans as +well, and you have to create a separate editor for those. This tutorial +goes through on how to edit an `Address` bean which is inside a `Person` +bean with the use of `CustomField` and `FieldGroup`. + +Here are the `Person` and `Address` beans + +[source,java] +.... +public class Person { + private String firstName; + private String lastName; + private Address address; + private String phoneNumber; + private String email; + private Date dateOfBirth; + private String comments; + + //Getters and setters +} +.... + +[source,java] +.... +public class Address { + private String street; + private String zip; + private String city; + private String country; + + // Getters and setters +} +.... + +[[creating-a-new-field]] +Creating a new field +~~~~~~~~~~~~~~~~~~~~ + +The first step is to create a new field which represents the editor for +the address. In this case the field itself will be a button. The button +will open a window where you have all the address fields. The address +will be stored back when the user closes the window. + +[source,java] +.... +public class AddressPopup extends CustomField
{ + @Override + protected Component initContent() { + return null; + } + + @Override + public Class
getType() { + return Address.class; + } +} +.... + +CustomField requires that you implement two methods, `initContent()` and +`getType()`. `initContent()` creates the actual visual representation of +your field. `getType()` tells the field which type of data will be handled +by the field. In our case it is an `Address` object so we return +`Address.class` in the method. + +[[creating-the-content]] +Creating the content +~~~~~~~~~~~~~~~~~~~~ + +Next up we create the actual button that will be visible in the person +editor when the CustomField is rendered. This button should open up a +new window where the user can edit the address. + +[source,java] +.... +@Override +protected Component initContent() { + final Window window = new Window("Edit address"); + final Button button = new Button("Open address editor", new ClickListener() { + public void buttonClick(ClickEvent event) { + getUI().addWindow(window); + } + }); + return button; +} +.... + +This is enough to attach the field to the person editor, but the window +will be empty and it won't modify the data in any way. + +[[creating-the-editable-fields]] +Creating the editable fields +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The address object contains four strings - street, zip, city and +country. For the three latter a `TextField` is good for editing, but the +street address can contain multiple row so a `TextArea` is better here. +All the fields have to be put into a layout and the layout has to be set +as the content of the window. `FormLayout` is a good choice here to nicely +align up the captions and fields of the window. + +[source,java] +.... +FormLayout layout = new FormLayout(); +TextArea street = new TextArea("Street address:"); +TextField zip = new TextField("Zip code:"); +TextField city = new TextField("City:"); +TextField country = new TextField("Country:"); +layout.addComponent(street); +layout.addComponent(zip); +layout.addComponent(city); +layout.addComponent(country); +window.setContent(layout); +.... + +The field is now visually ready but it doesn't contain or affect any +data. You want to also modify the sizes as well to make it look a bit +nicer: + +[source,java] +.... +window.center(); +window.setWidth(null); +layout.setWidth(null); +layout.setMargin(true); +.... + +[[binding-the-address-to-the-field]] +Binding the address to the field +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A FieldGroup can be used to bind the data of an Address bean into the +fields. We create a member variable for a FieldGroup and initialize it +within the createContent() -method: + +[source,java] +.... +fieldGroup = new BeanFieldGroup
(Address.class); +fieldGroup.bind(street, "street"); +fieldGroup.bind(zip, "zip"); +fieldGroup.bind(city, "city"); +fieldGroup.bind(country, "country"); +.... + +The `FieldGroup` of the person editor will call +`AddressPopup.setValue(person.getAddress())` when we start to edit our +person. We need to override `setInternalValue(Address)` to get the `Address` +object and pass it to the `FieldGroup` of the address editor. + +[source,java] +.... +@Override +protected void setInternalValue(Address address) { + super.setInternalValue(address); + fieldGroup.setItemDataSource(new BeanItem
(address)); +} +.... + +The last thing that has to be done is save the modifications made by the +user back into the `Address` bean. This is done with a `commit()` call to +the `FieldGroup`, which can be made for example when the window is closed: + +[source,java] +.... +window.addCloseListener(new CloseListener() { + public void windowClose(CloseEvent e) { + try { + fieldGroup.commit(); + } catch (CommitException ex) { + ex.printStackTrace(); + } + } +}); +.... + +Now you need to attach the `AddressPopup` custom field into the person +editor through it's `FieldGroup` and you have a working editor. + +[[complete-code]] +Complete code +~~~~~~~~~~~~~ + +[source,java] +.... +package com.example.addressforms.fields; + +import com.example.addressforms.data.Address; +import com.vaadin.data.fieldgroup.BeanFieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.data.util.BeanItem; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomField; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.CloseEvent; +import com.vaadin.ui.Window.CloseListener; + +public class AddressPopup extends CustomField
{ + private FieldGroup fieldGroup; + + @Override + protected Component initContent() { + FormLayout layout = new FormLayout(); + final Window window = new Window("Edit address", layout); + TextArea street = new TextArea("Street address:"); + TextField zip = new TextField("Zip code:"); + TextField city = new TextField("City:"); + TextField country = new TextField("Country:"); + layout.addComponent(street); + layout.addComponent(zip); + layout.addComponent(city); + layout.addComponent(country); + + fieldGroup = new BeanFieldGroup
(Address.class); + fieldGroup.bind(street, "street"); + fieldGroup.bind(zip, "zip"); + fieldGroup.bind(city, "city"); + fieldGroup.bind(country, "country"); + Button button = new Button("Open address editor", new ClickListener() { + public void buttonClick(ClickEvent event) { + getUI().addWindow(window); + } + }); + window.addCloseListener(new CloseListener() { + public void windowClose(CloseEvent e) { + try { + fieldGroup.commit(); + } catch (CommitException ex) { + ex.printStackTrace(); + } + } + }); + + window.center(); + window.setWidth(null); + layout.setWidth(null); + layout.setMargin(true); + return button; + } + + @Override + public Class
getType() { + return Address.class; + } + + @Override + protected void setInternalValue(Address address) { + super.setInternalValue(address); + fieldGroup.setItemDataSource(new BeanItem
(address)); + } +} +.... + +image:img/person%20editor.png[Address editor] + +image:img/address%20editor.png[Address editor window] diff --git a/documentation/articles/contents.asciidoc b/documentation/articles/contents.asciidoc index 28c9ef28e7..bb05866fd6 100644 --- a/documentation/articles/contents.asciidoc +++ b/documentation/articles/contents.asciidoc @@ -27,3 +27,4 @@ - link:FormattingDataInGrid.asciidoc[Formatting data in grid] - link:ConfiguringGridColumnWidths.asciidoc[Configuring Grid column widths] - link:Vaadin7HierarchicalContainerAndTreeComponentExampleWithLiferayOrganizationService.asciidoc[Vaadin 7 hierarchical container and TreeComponent example with Liferay OrganizationService] +- link:CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc[Creating a CustomField for editing the address of a person] diff --git a/documentation/articles/img/address editor.png b/documentation/articles/img/address editor.png new file mode 100644 index 0000000000..1dd60c3dc8 Binary files /dev/null and b/documentation/articles/img/address editor.png differ diff --git a/documentation/articles/img/person editor.png b/documentation/articles/img/person editor.png new file mode 100644 index 0000000000..71de0a3ebb Binary files /dev/null and b/documentation/articles/img/person editor.png differ