diff options
author | Alejandro <alejandro.d.a@gmail.com> | 2017-01-21 09:50:59 +0200 |
---|---|---|
committer | Matti Tahvonen <matti@vaadin.com> | 2017-01-21 09:50:59 +0200 |
commit | 19427ba7c7a51d3af61c170a7ba54137eb629ac8 (patch) | |
tree | dce04c3c51985e5acc545da06535de46cbc29f2e /documentation/tutorial.adoc | |
parent | cb264dacfe74cba1266b54df8ce8c6ded1510004 (diff) | |
download | vaadin-framework-19427ba7c7a51d3af61c170a7ba54137eb629ac8.tar.gz vaadin-framework-19427ba7c7a51d3af61c170a7ba54137eb629ac8.zip |
Updated tutorial to v.8.0.0.beta1 (#8298)
Diffstat (limited to 'documentation/tutorial.adoc')
-rw-r--r-- | documentation/tutorial.adoc | 190 |
1 files changed, 114 insertions, 76 deletions
diff --git a/documentation/tutorial.adoc b/documentation/tutorial.adoc index fa21af4391..908c2e603e 100644 --- a/documentation/tutorial.adoc +++ b/documentation/tutorial.adoc @@ -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 |