|
|
@@ -39,6 +39,8 @@ subnav: |
|
|
|
[[framework.tutorial]] |
|
|
|
= Vaadin Tutorial |
|
|
|
|
|
|
|
WARNING: Please keep in mind that some of the videos and screenshots in this tutorial were built with Vaadin Framework 7 and Designer 1.0. There are some small differences if you use the latest versions. |
|
|
|
|
|
|
|
This tutorial gives you an overview of how you can use https://vaadin.com/framework[Vaadin Framework] to build single-page web UIs for your Java application. |
|
|
|
All you need to start with it is JDK 8 and an https://en.wikipedia.org/wiki/Integrated_development_environment[IDE], such as Eclipse. |
|
|
|
While this tutorial is written for Eclipse users, you can use your IDE of choice. |
|
|
@@ -148,9 +150,7 @@ Creating your next Maven-based Vaadin project will be much faster. |
|
|
|
Right click on the newly created project and choose "Run as > Maven Install". |
|
|
|
This initiates a full build of your application and finally creates a https://en.wikipedia.org/wiki/WAR_(file_format)[WAR] file into the [filename]#target# directory. |
|
|
|
You can deploy the WAR file to your application server. |
|
|
|
The first build will take a while, as Maven might again need to download some new modules. |
|
|
|
Also, the project uses add-ons and contains a project specific theme. |
|
|
|
Compiling them takes a while. |
|
|
|
The first build might take a while, as Maven might again need to download some new modules. |
|
|
|
|
|
|
|
TIP: For the Maven compilation to work you need a JDK to be configured in your |
|
|
|
Eclipse in "Window > Preferences > Java > Installed JREs > Add...". |
|
|
@@ -245,11 +245,15 @@ video::9-qwPfpSHWc[youtube, width="640", height="400"] |
|
|
|
[[framework.tutorial.backend]] |
|
|
|
== Adding a demo "backend" |
|
|
|
|
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/v8-step2.zip[Download the project] for this step, extract the zip file and choose "Import... > Maven > Existing Maven project". |
|
|
|
|
|
|
|
Before getting more into real Vaadin development, let us introduce some domain objects and a "fake backend". |
|
|
|
In a real-world application, you will most likely have something similar, implemented with, for example, JPA and EJB or a Spring-based service. |
|
|
|
|
|
|
|
The following video covers steps 3 and 4 (<<framework.tutorial.grid>>) of this tutorial: |
|
|
|
|
|
|
|
WARNING: This video is built with Vaadin Framework 7. There are some small differences if you use the latest version. |
|
|
|
|
|
|
|
video::0W0frepDKWI[youtube, width="640", height="400"] |
|
|
|
|
|
|
|
Copy the following three classes from github to your project. |
|
|
@@ -272,7 +276,7 @@ The actual implementation of these classes is not relevant for this tutorial, bu |
|
|
|
[[framework.tutorial.grid]] |
|
|
|
== Listing entities in a Grid |
|
|
|
|
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/step3.zip[Download the project] for this step, extract the zip file and choose "Import... > Maven > Existing Maven project". |
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/v8-step3.zip[Download the project] for this step, extract the zip file and choose "Import... > Maven > Existing Maven project". |
|
|
|
|
|
|
|
Often when you start building a UI for a data-centric application, the first |
|
|
|
thing you want to do is to list your data from your back-end. |
|
|
@@ -288,7 +292,7 @@ Also, let us get a reference to the [classname]#CustomerService#. |
|
|
|
public class MyUI extends UI { |
|
|
|
// Add the next two lines: |
|
|
|
private CustomerService service = CustomerService.getInstance(); |
|
|
|
private Grid grid = new Grid(); |
|
|
|
private Grid<Customer> grid = new Grid<>(); |
|
|
|
|
|
|
|
// The rest is already there... |
|
|
|
@Override |
|
|
@@ -319,9 +323,8 @@ protected void init(VaadinRequest vaadinRequest) { |
|
|
|
|
|
|
|
// fetch list of Customers from service and assign it to Grid |
|
|
|
List<Customer> customers = service.findAll(); |
|
|
|
grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers)); |
|
|
|
grid.setItems(customers); |
|
|
|
|
|
|
|
layout.setMargin(true); |
|
|
|
setContent(layout); |
|
|
|
} |
|
|
|
---- |
|
|
@@ -340,18 +343,19 @@ Macs). The extracted method call looks like this: |
|
|
|
---- |
|
|
|
public void updateList() { |
|
|
|
List<Customer> customers = service.findAll(); |
|
|
|
grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers)); |
|
|
|
grid.setItems(customers); |
|
|
|
} |
|
|
|
---- |
|
|
|
|
|
|
|
If you try the application now, you'll see that quite many properties of the |
|
|
|
customers are shown in the grid. To limit the visible properties, configure |
|
|
|
the Grid using the _setColumns_ method to only show "firstName", "lastName" and |
|
|
|
If you try the application now, you'll see an empty Grid with no columns. To add columns, configure |
|
|
|
the Grid using the _addColumn_ method to show the "firstName", "lastName" and |
|
|
|
"email" properties. |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
grid.setColumns("firstName", "lastName", "email"); |
|
|
|
grid.addColumn(Customer::getFirstName).setCaption("First Name"); |
|
|
|
grid.addColumn(Customer::getLastName).setCaption("Last Name"); |
|
|
|
grid.addColumn(Customer::getEmail).setCaption("Email"); |
|
|
|
---- |
|
|
|
|
|
|
|
At this point the body of the MyUI class should look like this (servlet declaration |
|
|
@@ -366,20 +370,21 @@ private Grid grid = new Grid(); |
|
|
|
protected void init(VaadinRequest vaadinRequest) { |
|
|
|
final VerticalLayout layout = new VerticalLayout(); |
|
|
|
|
|
|
|
grid.setColumns("firstName", "lastName", "email"); |
|
|
|
grid.addColumn(Customer::getFirstName).setCaption("First Name"); |
|
|
|
grid.addColumn(Customer::getLastName).setCaption("Last Name"); |
|
|
|
grid.addColumn(Customer::getEmail).setCaption("Email"); |
|
|
|
// add Grid to the layout |
|
|
|
layout.addComponent(grid); |
|
|
|
|
|
|
|
updateList(); |
|
|
|
|
|
|
|
layout.setMargin(true); |
|
|
|
setContent(layout); |
|
|
|
} |
|
|
|
|
|
|
|
public void updateList() { |
|
|
|
// fetch list of Customers from service and assign it to Grid |
|
|
|
List<Customer> customers = service.findAll(); |
|
|
|
grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers)); |
|
|
|
grid.setItems(customers); |
|
|
|
} |
|
|
|
---- |
|
|
|
|
|
|
@@ -389,7 +394,7 @@ You can do this at any point during the rest of the tutorial as well. |
|
|
|
[[framework.tutorial.filtering]] |
|
|
|
== Creating live filtering for entities |
|
|
|
|
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/step4.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/v8-step4.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
|
|
|
|
A search functionality is expected in every modern application and it is |
|
|
|
also a nice Vaadin development exercise. Let's add a filtering functionality to |
|
|
@@ -397,6 +402,8 @@ the Customer listing we created in the previous step. |
|
|
|
|
|
|
|
The following video shows how to do this step of the tutorial: |
|
|
|
|
|
|
|
WARNING: This video is built with Vaadin Framework 7. There are some small differences if you use the latest version. |
|
|
|
|
|
|
|
video::fAeC_mZH_7w[youtube, width="640", height="400"] |
|
|
|
|
|
|
|
We'll start by introducing a [classname]#TextField# component as a field to our [classname]#UI# class: |
|
|
@@ -413,27 +420,25 @@ object. |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
filterText.setInputPrompt("filter by name..."); |
|
|
|
filterText.addTextChangeListener(e -> { |
|
|
|
grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, |
|
|
|
service.findAll(e.getText()))); |
|
|
|
}); |
|
|
|
filterText.setPlaceholder("filter by name..."); |
|
|
|
filterText.addValueChangeListener(e -> updateList()); |
|
|
|
filterText.setValueChangeMode(ValueChangeMode.LAZY); |
|
|
|
---- |
|
|
|
|
|
|
|
TIP: To keep your code more readable, you can use autoformat after you write or |
|
|
|
copy paste code snippets. The default keyboard shortcut in Eclipse is |
|
|
|
kbd:[Ctrl+Shift+F] or kbd:[Cmd+Shift+F] |
|
|
|
|
|
|
|
The text change listener is another listener (in addition to the more commonly |
|
|
|
used ValueChangeListener) you can use with text fields in Vaadin. It is fired |
|
|
|
lazily while the user is typing, but only when there is a small pause in the |
|
|
|
typing. This makes it perfect for this kind of automatic filtering. When the |
|
|
|
user has changed the text, we'll just update the listing like in the updateList |
|
|
|
method, but use the current text as a filter for entries. |
|
|
|
As its name implies, the value change listener allows you to react to changes in |
|
|
|
the value contained in the text field. It is configured so that the event is fired |
|
|
|
lazily while the user is typing, when there is a small pause in the typing. |
|
|
|
This makes it perfect for this kind of automatic filtering. When the |
|
|
|
user has changed the text, we'll just update the listing calling the _updateList_ |
|
|
|
method. |
|
|
|
|
|
|
|
To keep the _updateList_ method functional, it should also take into |
|
|
|
consideration the possible value in the filterText field. Change the line for |
|
|
|
fetching the customers into this: |
|
|
|
To keep the _updateList_ method functional, it should take into consideration |
|
|
|
the possible value in the filterText field. Change the line for fetching the |
|
|
|
customers into this: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
@@ -444,31 +449,27 @@ Before adding the text field to the UI, let's improve the usability a bit |
|
|
|
and make a short exercise to compose better components from lower level UI |
|
|
|
components. The search field can naturally be cleared with the keyboard, but let's |
|
|
|
add a clear button next to the text field. Start by adding the following lines |
|
|
|
to the init method, for example right after your filterText configuration: |
|
|
|
to the init method, for example right after your _filterText_ configuration: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
Button clearFilterTextBtn = new Button(FontAwesome.TIMES); |
|
|
|
clearFilterTextBtn.setDescription("Clear the current filter"); |
|
|
|
clearFilterTextBtn.addClickListener(e -> { |
|
|
|
filterText.clear(); |
|
|
|
updateList(); |
|
|
|
}); |
|
|
|
clearFilterTextBtn.addClickListener(e -> filterText.clear()); |
|
|
|
---- |
|
|
|
|
|
|
|
Vaadin contains a set of built in icons, from which we use the "X" icon, |
|
|
|
_FontAwesome.TIMES_, here, which most users will recognise as a functionality to clear |
|
|
|
the value. If we set the description to a component, it will be shown as a |
|
|
|
tooltip for those users who hover the cursor over the button and wonder what to |
|
|
|
do with it. In the click listener, we simply clear the text from the field and |
|
|
|
refresh the content of the listing. |
|
|
|
do with it. In the click listener, we simply clear the text from the field. |
|
|
|
|
|
|
|
Vaadin contains lots of different kinds of layouts. The simplest way to align |
|
|
|
the text field and the button next to each other would be to use a |
|
|
|
HorizontalLayout. An alternative way we use here is using a CssLayout, which is |
|
|
|
a lightweight layout that is easy to customize with css. Even if you wouldn't |
|
|
|
want to play with CSS yourself, you can often use one of the existing style |
|
|
|
rules in the default _Valo_ theme. The following snippet will create a nice |
|
|
|
rules in the default https://demo.vaadin.com/valo-theme[_Valo_] theme. The following snippet will create a nice |
|
|
|
compact "composition" of both the TextField and the clear button. Add these |
|
|
|
lines to the init method right after you configured the _clearFilterTextBtn_: |
|
|
|
|
|
|
@@ -479,7 +480,7 @@ filtering.addComponents(filterText, clearFilterTextBtn); |
|
|
|
filtering.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP); |
|
|
|
---- |
|
|
|
|
|
|
|
Finally, *change* the row in the init method that currently adds only the grid, |
|
|
|
Finally, *change* the line in the init method that currently adds only the grid, |
|
|
|
to add both _filtering_ composition and the _grid_ to the main _layout_ of the |
|
|
|
application. |
|
|
|
|
|
|
@@ -500,7 +501,7 @@ that. Pick either of them. |
|
|
|
[[framework.tutorial.form.designer]] |
|
|
|
=== Creating a form using Vaadin Designer |
|
|
|
|
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/step5.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/v8-step5.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
|
|
|
|
The form to edit Customer objects can be built using several methods of which |
|
|
|
the visual composition by drag 'n' drop is the most intuitive. Vaadin |
|
|
@@ -542,6 +543,8 @@ The following screencast will show you how to produce the |
|
|
|
_CustomerFormDesign.html_, a design file we need in this tutorial. Use pause and |
|
|
|
slow motion to follow better what is being done in the video. Feel free to get creative! |
|
|
|
|
|
|
|
WARNING: This video is built with Designer 1.0. There are some small differences if you use the latest version. |
|
|
|
|
|
|
|
video::B5dN69NSS78[youtube, width="640", height="400"] |
|
|
|
|
|
|
|
TIP: At any point of the process, you can also switch to the markup mode where |
|
|
@@ -597,7 +600,6 @@ all of the available space more efficiently. Replace the line |
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
HorizontalLayout main = new HorizontalLayout(grid, form); |
|
|
|
main.setSpacing(true); |
|
|
|
main.setSizeFull(); |
|
|
|
grid.setSizeFull(); |
|
|
|
main.setExpandRatio(grid, 1); |
|
|
@@ -615,7 +617,7 @@ following line to the constructor: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
status.addItems(CustomerStatus.values()); |
|
|
|
status.setItems(CustomerStatus.values()); |
|
|
|
---- |
|
|
|
|
|
|
|
Let's also improve the UX a bit. When building the design, we already |
|
|
@@ -631,8 +633,28 @@ save.setClickShortcut(KeyCode.ENTER); |
|
|
|
|
|
|
|
To finish our form, we need to create a public API that we will use in the next |
|
|
|
part from MyUI, to pass in a Customer object that the form should edit. We |
|
|
|
will also add some logic to actually save the changes. We'll start by creating a |
|
|
|
setter method to the Customer field. Just type _setCus_ in the body of the |
|
|
|
will also add some logic to actually save the changes. We'll start by adding a |
|
|
|
_BeanBinder_ as a field to the _CustomerForm_ class: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
private BeanBinder<Customer> beanBinder = new BeanBinder<>(Customer.class); |
|
|
|
---- |
|
|
|
|
|
|
|
In the constructor of the CustomerForm class add the following line to configure |
|
|
|
the BeanBinder: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
beanBinder.bindInstanceFields(this); |
|
|
|
---- |
|
|
|
|
|
|
|
This configures the BeanBinder to use all the similary named editor fields in |
|
|
|
this form to bind their values with their counterpart in the Customer class. |
|
|
|
For example, the _CustomerForm.firstName_ TextField will be bound to the |
|
|
|
Customer.firstName property. |
|
|
|
|
|
|
|
Create a setter method for the Customer field. Just type _setCus_ in the body of the |
|
|
|
class and hit autocomplete (kbd:[Ctrl+Space]) and Eclipse will create a method |
|
|
|
stub for you. Complete it with the following implementation: |
|
|
|
|
|
|
@@ -640,7 +662,7 @@ stub for you. Complete it with the following implementation: |
|
|
|
---- |
|
|
|
public void setCustomer(Customer customer) { |
|
|
|
this.customer = customer; |
|
|
|
BeanFieldGroup.bindFieldsUnbuffered(customer, this); |
|
|
|
beanBinder.setBean(customer); |
|
|
|
|
|
|
|
// Show delete button for only customers already in the database |
|
|
|
delete.setVisible(customer.isPersisted()); |
|
|
@@ -650,11 +672,9 @@ public void setCustomer(Customer customer) { |
|
|
|
---- |
|
|
|
|
|
|
|
In addition to saving the reference of the currently edited Customer object, we are |
|
|
|
calling the _BeanFieldGroup.bindFieldsUnbuffered_ method. It will initialize all |
|
|
|
similarly named editor fields in this form with the values from their |
|
|
|
counterpart in the given Customer object. Also, it will automatically update the |
|
|
|
values in the domain objects as the corresponding field value changes in the |
|
|
|
user interface. |
|
|
|
calling the _BeanBinder.setBean_ method. This will initialise all |
|
|
|
fields in the form and automatically update the values in the domain objects as |
|
|
|
the corresponding field value changes in the user interface. |
|
|
|
|
|
|
|
TIP: If the naming convention based databinding doesn't fit your needs, you |
|
|
|
can use |
|
|
@@ -689,8 +709,8 @@ simple lambda expressions to the constructor will take care of that: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
save.addClickListener(e->this.save()); |
|
|
|
delete.addClickListener(e->this.delete()); |
|
|
|
save.addClickListener(e -> this.save()); |
|
|
|
delete.addClickListener(e -> this.delete()); |
|
|
|
---- |
|
|
|
|
|
|
|
TIP: For a truly re-usable form component in a real life project, you'd want to |
|
|
@@ -702,6 +722,8 @@ simplicity. |
|
|
|
[[framework.tutorial.form.java]] |
|
|
|
=== Creating a form using plain Java |
|
|
|
|
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/v8-step5.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
|
|
|
|
This is an alternative step to the <<Creating a form using Vaadin Designer>>, |
|
|
|
where you'll build the form UI programmatically in plain Java. If you already |
|
|
|
completed the step using Vaadin Designer, you can proceed to |
|
|
@@ -709,6 +731,8 @@ completed the step using Vaadin Designer, you can proceed to |
|
|
|
|
|
|
|
The following video shows how to create a form using plain Java: |
|
|
|
|
|
|
|
WARNING: This video is built with Vaadin Framework 7. There are some small differences if you use the latest version. |
|
|
|
|
|
|
|
video::OA6-lSxiXO0[youtube, width="640", height="400"] |
|
|
|
|
|
|
|
Start by creating a new Java class with the name CustomerForm. In Eclipse right |
|
|
@@ -718,7 +742,7 @@ click _finish_. |
|
|
|
|
|
|
|
In the form, we'll need editor fields for each property in our Customer domain |
|
|
|
class. There are different kinds of fields in Vaadin for editing different kinds |
|
|
|
of properties. In this example, we'll use a TextField, a PopupDateField and a |
|
|
|
of properties. In this example, we'll use a TextField, a DateField and a |
|
|
|
NativeSelect. Add the following field declarations and action buttons as Java |
|
|
|
fields to the CustomerForm: |
|
|
|
|
|
|
@@ -727,8 +751,8 @@ fields to the CustomerForm: |
|
|
|
private TextField firstName = new TextField("First name"); |
|
|
|
private TextField lastName = new TextField("Last name"); |
|
|
|
private TextField email = new TextField("Email"); |
|
|
|
private NativeSelect status = new NativeSelect("Status"); |
|
|
|
private PopupDateField birthdate = new PopupDateField("Birthday"); |
|
|
|
private NativeSelect<CustomerStatus> status = new NativeSelect<>("Status"); |
|
|
|
private DateField birthdate = new DateField("Birthday"); |
|
|
|
private Button save = new Button("Save"); |
|
|
|
private Button delete = new Button("Delete"); |
|
|
|
---- |
|
|
@@ -748,7 +772,6 @@ public CustomerForm(MyUI myUI) { |
|
|
|
|
|
|
|
setSizeUndefined(); |
|
|
|
HorizontalLayout buttons = new HorizontalLayout(save, delete); |
|
|
|
buttons.setSpacing(true); |
|
|
|
addComponents(firstName, lastName, email, status, birthdate, buttons); |
|
|
|
} |
|
|
|
---- |
|
|
@@ -773,7 +796,6 @@ all of the available space more efficiently. Replace the line |
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
HorizontalLayout main = new HorizontalLayout(grid, form); |
|
|
|
main.setSpacing(true); |
|
|
|
main.setSizeFull(); |
|
|
|
grid.setSizeFull(); |
|
|
|
main.setExpandRatio(grid, 1); |
|
|
@@ -791,7 +813,7 @@ following line to the constructor: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
status.addItems(CustomerStatus.values()); |
|
|
|
status.setItems(CustomerStatus.values()); |
|
|
|
---- |
|
|
|
|
|
|
|
Let's also improve the UX a bit. The most common thing your users will want to |
|
|
@@ -807,8 +829,28 @@ save.setClickShortcut(KeyCode.ENTER); |
|
|
|
|
|
|
|
To finish our form, we need to create a public API that we will use in the next |
|
|
|
part from the MyUI, to pass in a Customer object that the form should edit. We |
|
|
|
will also add some logic to actually save the changes. We'll start by creating a |
|
|
|
setter method for the Customer field. Just type _setCus_ in the body of the |
|
|
|
will also add some logic to actually save the changes. We'll start by adding a |
|
|
|
_BeanBinder_ as a field to the _CustomerForm_ class: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
private BeanBinder<Customer> beanBinder = new BeanBinder<>(Customer.class); |
|
|
|
---- |
|
|
|
|
|
|
|
In the constructor of the CustomerForm class add the following line to configure |
|
|
|
the BeanBinder: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
beanBinder.bindInstanceFields(this); |
|
|
|
---- |
|
|
|
|
|
|
|
This configures the BeanBinder to use all the similary named editor fields in |
|
|
|
this form to bind their values with their counterpart in the Customer class. |
|
|
|
For example, the _CustomerForm.firstName_ TextField will be bound to the |
|
|
|
Customer.firstName property. |
|
|
|
|
|
|
|
Create a setter method for the Customer field. Just type _setCus_ in the body of the |
|
|
|
class and hit autocomplete (kbd:[Ctrl+Space]) and Eclipse will create a method |
|
|
|
stub for you. Complete it with the following implementation: |
|
|
|
|
|
|
@@ -816,7 +858,7 @@ stub for you. Complete it with the following implementation: |
|
|
|
---- |
|
|
|
public void setCustomer(Customer customer) { |
|
|
|
this.customer = customer; |
|
|
|
BeanFieldGroup.bindFieldsUnbuffered(customer, this); |
|
|
|
beanBinder.setBean(customer); |
|
|
|
|
|
|
|
// Show delete button for only customers already in the database |
|
|
|
delete.setVisible(customer.isPersisted()); |
|
|
@@ -826,15 +868,13 @@ public void setCustomer(Customer customer) { |
|
|
|
---- |
|
|
|
|
|
|
|
In addition to saving the reference of the currently edited Customer object, we are |
|
|
|
calling _BeanFieldGroup.bindFieldsUnbuffered_ method. It will initialise all |
|
|
|
similarly named editor fields in this form with the values from their |
|
|
|
counterpart in the given Customer object. Also, it will automatically update the |
|
|
|
values in the domain objects as the corresponding field value changes in the |
|
|
|
user interface. |
|
|
|
calling the _BeanBinder.setBean_ method. This will initialise all |
|
|
|
fields in the form and automatically update the values in the domain objects as |
|
|
|
the corresponding field value changes in the user interface. |
|
|
|
|
|
|
|
TIP: If the naming convention based databinding doesn't fit your needs, you |
|
|
|
can use |
|
|
|
https://www.vaadin.com/api/com/vaadin/data/fieldgroup/PropertyId.html[PropertyId] |
|
|
|
https://www.vaadin.com/api/com/vaadin/annotations/PropertyId.html[PropertyId] |
|
|
|
annotation on fields to explicitly declare the edited property. |
|
|
|
|
|
|
|
We'll also want to ensure the form is visible and that the focus goes to the |
|
|
@@ -865,8 +905,8 @@ simple lambda expressions to the constructor will take care of that: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
save.addClickListener(e->this.save()); |
|
|
|
delete.addClickListener(e->this.delete()); |
|
|
|
save.addClickListener(e -> this.save()); |
|
|
|
delete.addClickListener(e -> this.delete()); |
|
|
|
---- |
|
|
|
|
|
|
|
TIP: For a truly re-usable form component in a real life project, you'd want to |
|
|
@@ -878,7 +918,7 @@ simplicity. |
|
|
|
[[framework.tutorial.form-connection]] |
|
|
|
== Connecting the form to the application |
|
|
|
|
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/step6.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/v8-step6.zip[Download the project] for this step, extract the zip file and choose menu:Import...[Maven>Existing Maven project]. |
|
|
|
|
|
|
|
In this part, we'll use the CustomerForm class, which we created in the |
|
|
|
previous step, from the MyUI class. We will use it for both editing the existing |
|
|
@@ -902,12 +942,11 @@ the end of the _init_ method: |
|
|
|
|
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
grid.addSelectionListener(event -> { |
|
|
|
if (event.getSelected().isEmpty()) { |
|
|
|
grid.asSingleSelect().addValueChangeListener(event -> { |
|
|
|
if (event.getValue() == null) { |
|
|
|
form.setVisible(false); |
|
|
|
} else { |
|
|
|
Customer customer = (Customer) event.getSelected().iterator().next(); |
|
|
|
form.setCustomer(customer); |
|
|
|
form.setCustomer(event.getValue()); |
|
|
|
} |
|
|
|
}); |
|
|
|
---- |
|
|
@@ -927,7 +966,7 @@ right after where you introduced the _filtering_ composition: |
|
|
|
---- |
|
|
|
Button addCustomerBtn = new Button("Add new customer"); |
|
|
|
addCustomerBtn.addClickListener(e -> { |
|
|
|
grid.select(null); |
|
|
|
grid.asSingleSelect().clear(); |
|
|
|
form.setCustomer(new Customer()); |
|
|
|
}); |
|
|
|
---- |
|
|
@@ -942,7 +981,6 @@ this after the previously created _addCustomerBtn_: |
|
|
|
[source,java] |
|
|
|
---- |
|
|
|
HorizontalLayout toolbar = new HorizontalLayout(filtering, addCustomerBtn); |
|
|
|
toolbar.setSpacing(true); |
|
|
|
---- |
|
|
|
|
|
|
|
And, again, *replace* the line that populates your main layout to add the |