]> source.dussan.org Git - vaadin-framework.git/commitdiff
Migrate CreatingACustomFieldFOrEditingTheAddressOfAPerson
authorErik Lumme <erik@vaadin.com>
Fri, 15 Sep 2017 10:08:23 +0000 (13:08 +0300)
committerErik Lumme <erik@vaadin.com>
Fri, 15 Sep 2017 10:08:23 +0000 (13:08 +0300)
documentation/articles/CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc [new file with mode: 0644]
documentation/articles/contents.asciidoc
documentation/articles/img/address editor.png [new file with mode: 0644]
documentation/articles/img/person editor.png [new file with mode: 0644]

diff --git a/documentation/articles/CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc b/documentation/articles/CreatingACustomFieldForEditingTheAddressOfAPerson.asciidoc
new file mode 100644 (file)
index 0000000..a28b631
--- /dev/null
@@ -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<Address> {
+  @Override
+  protected Component initContent() {
+    return null;
+  }
+
+  @Override
+  public Class<Address> 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>(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>(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<Address> {
+  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>(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<Address> getType() {
+    return Address.class;
+  }
+
+  @Override
+  protected void setInternalValue(Address address) {
+    super.setInternalValue(address);
+    fieldGroup.setItemDataSource(new BeanItem<Address>(address));
+  }
+}
+....
+
+image:img/person%20editor.png[Address editor]
+
+image:img/address%20editor.png[Address editor window]
index 28c9ef28e7556c6393f467215eb315d33d94e16b..bb05866fd682b648b2f1da1233545fb017277c67 100644 (file)
@@ -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 (file)
index 0000000..1dd60c3
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 (file)
index 0000000..71de0a3
Binary files /dev/null and b/documentation/articles/img/person editor.png differ