123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884 |
- :experimental:
- :sectnums:
- :imagesdir: img
-
- = Vaadin tutorial
-
- This tutorial gives you an overview of how you can use
- https://vaadin.com/framework[Vaadin Framework] to build single-page web UI's 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] like Eclipse.
- No extensive knowledge of Java is even needed to get started, only the basic programming skills are required. Although the tutorial is built for
- Eclipse users, you can use your IDE of choice.
-
- We'll build a simple customer management system. It is not a real app, but we'll
- use an in-memory "backend" so that you can understand how to hook it to an
- existing Java based backend. We'll cover the basic Vaadin development and you
- can use the result as a basis for more experiments with Vaadin, like using
- add-ons, your own custom look and feel (aka. theme), adding new views or optimizing the result for
- mobile support.
-
- You'll need about 20 - 60 minutes to complete the tutorial, depending on your
- existing experience, but naturally you can just do the beginning of
- the exercise or pick any of the steps you want. To start from a specific step,
- we have prepared the example code after each step to be
- downloaded as a zip file. If don't want to do the exercise at all, you can also
- just https://github.com/vaadin/tutorial/[downlood the final application] and
- play around with it.
-
- The tutorial uses Java 8, so ensure you have an up-to-date JDK 8 installed. Most
- linux distributions can use package managers to install JDK8, Windows and Mac users should
- download it from
- http://www.oracle.com/technetwork/java/javase/downloads/index.html[Oracle's Java
- SE site].
-
- Also make sure you have the latest version of your IDE. Eclipse is available in
- various packages, be sure to download the *Eclipse IDE for Java EE Developers*
- from http://www.eclipse.org/downloads/[eclipse.org].
-
- == Creating a project using an archetype
-
- As a starting point for the application, we'll use a Maven archetype called
- vaadin-archetype-application. Maven archetypes are project stubs with basic
- build script and some example code.
-
- Start by choosing menu:File[New > Maven Project] from the menu.
-
- image::createMavenProject.jpg[Create a new Maven built Vaadin project.]
-
- TIP: If the "Maven Project" is not visible in the menu, you should switch to the
- _Java EE_ perspective. Use the shortcut button in the toolbar or
- menu:Window[Perspective] to do this.
-
- The first page in the wizard is ok with its defaults, but on the second page
- you'll need to choose _vaadin-archetype-application_ archetype. You can first
- try to find it using the filtering function, but in some cases Eclipse hasn't
- yet indexed the archetype catalog, so you might need to manually add the
- archetype details with the _Add Archetype_ button. The Group Id is _com.vaadin_,
- the Artifact Id is _vaadin-archetype-application_ and as a version you can use
- the latest Vaadin version, at the time of writing _7.6.2_. The _Repository URL_
- can be left blank.
-
- CAUTION: Eclipse has a bug in its project wizard. If
- _vaadin-archetype-application_ doesn't appear in the listing, even though you
- added it using the _Add Archetype_ button, close the whole new project wizard
- and re-open it by selecting menu:File[New > Maven Project] again. The archetype
- then typically appears in the listing and can be found by the filtering
- functionality.
-
- On the next wizard page, type in _my.vaadin_ as the Group Id, _app_ as the
- Artifact Id and click _Finish_. If this is your first Vaadin app, creating
- a project might take a while, depending on the speed of your network, as Vaadin
- libraries and other dependencies are being downloaded. Maven caches these on
- your local file system and creating your next Maven based Vaadin project will be much
- faster.
-
- Right click on the newly created project and choose menu:Run as[Maven Install].
- This will initiate a full build of your application and will finally create a
- https://en.wikipedia.org/wiki/WAR_(file_format)[war] file to the "target" directory that you can deploy to your application
- server. As Maven might again need to download some new modules and the project
- has a setup for add-on usage and contains a project specific theme, the first
- build will take a while.
-
- TIP: For the Maven compilation to work you need a JDK to be configured in your
- Eclipse in menu:Window[Preferences > Java > Installed JREs > Add...]. This step
- is necessary at least on Windows, if you are using a fresh installation of
- Eclipse or for some other reason haven't configured a JDK to your Eclipse. The
- JDK by default installs to _\Program Files\Java_ on Windows. You
- can make JDK the default JRE for your Eclipse.
-
- While the build is running, let's have a look at what the archetype created for
- you. You can browse your project resources from the tree structure in the
- _Project Explorer_. Maven's _pom.xml_ on top level contains settings for your
- projects build and declares the used dependencies. Open _Java Resources_ and
- below it _src/main/java_, the main source directory, and _my.vaadin.app_, the
- main Java package that will contain your Vaadin UI code.
-
- TIP: Eclipse shows all project files in the Project Explorer. In this case you
- can also find your _.java_ files via top level _src_ node, but the suggested
- method is to access them via the _Java Resources_ node, which is optimized for
- editing Java source code.
-
- The UI code (and the Servlet declaration) used by the application stub can be
- found in the _MyUI.java_ file. Let's read it through to see how it works. The
- _init_ method of a UI class is triggered when a user enters your web
- application. The VerticalLayout is one of the most used layout objects, which
- are used to position and display other Vaadin components in your UI classes. The
- example code creates one TextField to allow the user to input her name and a
- Button whose click listener dynamically adds a new Label component to the main
- layout. In the end of the init method we just configure the main layout and
- place components into it and set it to be the content of MyUI.
-
- To test your first Vaadin application, right click on the project and choose
- menu:Debug as[Maven build...]. The debug mode is slightly slower than the basic run
- mode, but it often helps you to figure out what is happening in your
- application.
-
- image::debugAsMavenBuild.jpg[Starting the server using a Maven target]
-
- In the dialog, type _Run in jetty_ to the _Name_ input and _jetty:run_ to the
- _Goals_ input.
-
- image::debugAsMavenBuild2.jpg[Generating a Maven launch for jetty:run target]
-
- Before clicking debug, to make sure debugging works properly, add your Java
- project to the source lookup path from the _Source_ tab, like it is being done
- in the image below.
-
- image::debugAsMavenBuildAddSources.jpg[Adding sources for debugging]
-
- Now click _Debug_ to continue. This will download a small Java web server
- (if not cached to your local Maven repository), and use it to host
- your application. Once the server has started, point your browser to the URL
- http://localhost:8080/[http://localhost:8080/] to see the running application.
-
- If you make changes to the code, the jetty server will notice the changes and in
- a couple of seconds most changes are automatically deployed. Reloading the page
- in your browser will show the changes.
-
- TIP: In some cases your JVM might not allow injecting changes on the fly. In
- these cases, Eclipse will complain about "Hot code replacement error". Just
- choose to restart the server to get the latest changes. Many Java developers use
- a commercial tool called http://zeroturnaround.com/software/jrebel/[JRebel] to make code
- replacement work better.
-
- Mastering the usage of the java debugger is also handy to better understand how your
- application actually works and fixing bugs that all developers write at some
- point. As Vaadin is "only" Java code, you can use all of Java's debugging tools, which cannot be done with other UI frameworks where the UI is written (partly) in HTML and/or JavaScript. Double click on the line number in the Java editor, for example of the
- following line in the click listener:
-
- [source,java]
- ----
- layout.addComponent(new Label("Thanks " + name.getValue()
- ----
-
- This will add a breakpoint to the selected line. If you then click the button in
- your browser, the execution of the application will stop on that line. Eclipse
- will ask you to enter to _Debugging perspective_ and you can inspect its
- variables and step through the execution. Clicking on the _play_ icon in the
- toolbar will continue the execution. Double click the same line again to remove
- the breakpoint.
-
- image::debugInBreakPointVariable.jpg[Execution in a break point in the button click listener]
-
- Clicking the red square in the Console view will terminate the server process.
- You can restart it easily form the run/debug history. You can find that from the
- small down arrow next to the green play button or bug button (for the debug
- mode) in the toolbar. Alternatively you can use the main menu menu:Run[Run
- history/Debug history > Run in Jetty].
-
- To get back to the _Java EE Perspective_, an Eclipse mode designed for editing
- Java web app code, click the _Java EE_ button in the toolbar.
-
- == Adding a demo "backend"
-
- Before getting more into real Vaadin development, let's introduce some domain
- objects and a "fake backend". In a real world application, you'll most likely
- have something similar, implemented with, for example, JPA and EJB or a Spring based
- service.
-
- Copy the following three classes from github to your project. Class names
- point to the classes hosted in Github. Copying classes can be done in many ways.
-
- TIP: The fastest way to copy classes using Eclipse is to use your good old
- clipboard. Select the text content of the whole class from your browser, choose
- menu:Edit[Copy], focus the node representing the _my.vaadin.app_ Java package in
- Eclipse's Java Resources view and choose menu:Edit[Paste]. Eclipse is smart
- enough to automatically create a properly named Java file for the class.
-
- * https://raw.githubusercontent.com/vaadin/tutorial/master/src/main/java/my/vaadin/app/CustomerStatus.java[CustomerStatus] - this is a simple enum class
- * https://raw.githubusercontent.com/vaadin/tutorial/master/src/main/java/my/vaadin/app/Customer.java[Customer] - this is the main domain object, a basic Java bean that we'll be
- using in our example
- * https://raw.githubusercontent.com/vaadin/tutorial/master/src/main/java/my/vaadin/app/CustomerService.java[CustomerService] - this is a simple facade via which you can request and modify Customer instances. You can think of this as your entry point to your fake database.
-
- In the next steps, we'll be using these classes and build a UI around them. The
- actual implementation of these classes is not relevant for this tutorial, but
- feel free to have a look around.
-
- == Listing entities in a Grid
-
- TIP: Starting from this step directly? https://github.com/vaadin/tutorial/archive/step2.zip[Download the project] for this step, extract the zip file and choose menu: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 backend. There are several
- components and methods in Vaadin to do this. In this example, we'll use the Grid
- component for tabular presentation of our customers.
-
- We'll start by introducing a Grid field to the MyUI class. We could of course
- just introduce the Grid as a variable in the init method, but we'll most likely
- want to refer to it later. Also, let's get a reference to the CustomerService.
-
- [source,java]
- ----
- public class MyUI extends UI {
-
- // Add next two lines:
- private CustomerService service = CustomerService.getInstance();
- private Grid grid = new Grid();
-
- // the rest is already there...
- @Override
- protected void init(VaadinRequest vaadinRequest) {
- ----
-
- TIP: If you are new to Java development, you probably don't feel comfortable
- with the red compilation error for the line where the Grid got introduced, due
- to a missing import. This is easily fixed in Eclipse by using the
- menu:Source[Organize Imports] command. Learn its shortcut (kbd:[Ctrl-Shift-O] or
- kbd:[CMD-Shift-O] on Macs), you'll be using it a lot in Java development. In
- possible class name collisions, always choose the appropriate class from the
- _com.vaadin.ui_ package if you want to import core Vaadin UI classes like the
- Grid.
-
- To simply list all properties of all Customer objects from the backend service,
- replace the init method with the following snippet:
-
- [source,java]
- ----
- @Override
- protected void init(VaadinRequest vaadinRequest) {
- final VerticalLayout layout = new VerticalLayout();
-
- // add Grid to the layout
- layout.addComponents(grid);
-
- // fetch list of Customers from service and assign it to Grid
- List<Customer> customers = service.findAll();
- grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers));
-
- layout.setMargin(true);
- setContent(layout);
- }
- ----
-
- TIP: Again, use the organize imports feature. The List object we use here is
- _java.util.List_.
-
- As we'll want to refresh the listing from various places in our application,
- extract the customer listing part into its own "updateList" method with the
- *public* modifier. The public modifier is handy later when we want to update the
- listing from other classes. You can let Eclipse help here by selecting the
- relevant lines and using the "quick fix" feature (kbd:[Ctrl+1] or kbd:[Cmd+1] on
- Macs). The extracted method call looks like this:
-
- [source,java]
- ----
- public void updateList() {
- List<Customer> customers = service.findAll();
- grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, 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
- "email" properties.
-
- [source,java]
- ----
- grid.setColumns("firstName", "lastName", "email");
- ----
-
- At this point the body of the MyUI class should look like this (servlet declaration
- omitted):
-
- [source,java]
- ----
- private CustomerService service = CustomerService.getInstance();
- private Grid grid = new Grid();
-
- @Override
- protected void init(VaadinRequest vaadinRequest) {
- final VerticalLayout layout = new VerticalLayout();
-
- grid.setColumns("firstName", "lastName", "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));
- }
- ----
-
- You can now save your changes to the file and verify the changes from your browser.
- You can do this at any point during the rest of the tutorial as well.
-
- == Creating live filtering for entities
-
- 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 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
- the Customer listing we created in the previous step.
-
- We'll start by introducing a TextField component as a field to our UI class:
-
- [source,java]
- ----
- private TextField filterText = new TextField();
- ----
-
- In the _init_ method, configure the text field to contain a helpful input prompt
- and add a text change listener to the field. The exact place of these lines is
- not important, but add them, for example, after you have introduced the _layout_
- object.
-
- [source,java]
- ----
- filterText.setInputPrompt("filter by name...");
- filterText.addTextChangeListener(e -> {
- grid.setContainerDataSource(new BeanItemContainer<>(Customer.class,
- service.findAll(e.getText())));
- });
- ----
-
- 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.
-
- 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:
-
- [source,java]
- ----
- List<Customer> customers = service.findAll(filterText.getValue());
- ----
-
- 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:
-
- [source,java]
- ----
- Button clearFilterTextBtn = new Button(FontAwesome.TIMES);
- clearFilterTextBtn.setDescription("Clear the current filter");
- clearFilterTextBtn.addClickListener(e -> {
- filterText.clear();
- updateList();
- });
- ----
-
- 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.
-
- 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
- compact "composition" of both the TextField and the clear button. Add these
- lines to the init method right after you configured the _clearFilterTextBtn_:
-
- [source,java]
- ----
- CssLayout filtering = new CssLayout();
- filtering.addComponents(filterText, clearFilterTextBtn);
- filtering.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
- ----
-
- Finally, *change* the row 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.
-
- [source,java]
- ----
- layout.addComponents(filtering, grid);
- ----
-
- Now it is a good place to save your changes and try them in your browser.
-
- == Creating a form to edit Customer objects
-
- To edit and add Customer objects we need to create a form, that edits the
- values in our domain objects. This tutorial has two alternative methods to do
- that. Pick either of them.
-
- === Creating a form using Vaadin Designer
-
- 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].
-
- 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
- Designer is an Eclipse plugin that you can install and do WYSIWYG editing of
- your view code. We'll use it to create the form and then hook the editing logic
- to it with Java.
-
- TIP: If you are using another IDE or just prefer to compose your user interface
- with code, take the alternative step, <<Creating a form using plain Java>>,
- where the CustomerForm is composed using plain Java code.
-
- ==== Installing Vaadin Designer
-
- Vaadin Designer comes as an integrated part of Vaadin Plugin for Eclipse. It can
- be installed easily via Eclipse Marketplace. Choose menu:Help[Eclipse Marketplace]
-
- In the dialog, just search for Vaadin and click _install_ to mark it for
- installation. Clicking _Install Now_ will take you to choose the modules you want
- and accept the license agreement.
-
- image::pluginEclipseMarketPlace2.jpg[Selecting Vaadin Plugin for Eclipse for installation in Eclipse Marketplace]
-
- If you get a security warning about the software containing unsigned content,
- just accept the warning by clicking OK. After installation, Eclipse asks if you
- want to restart. Click Yes.
-
- TIP: When you use Vaadin Designer for the first time in the next
- step, it will ask for a license key. Get a key from
- https://vaadin.com/designer. If you are not willing to buy a license now, just
- acquire a trial license.
-
- ==== Creating the form design
-
- 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!
-
- video::B5dN69NSS78[youtube, width="640", height="400"]
-
- TIP: At any point of the process, you can also switch to the markup mode where
- you can edit the raw content of the .html file. If you wish to take a shortcut
- or think you did something wrong when using the designer, you can just
- copy-paste the content of https://github.com/vaadin/tutorial/blob/master/src/main/resources/my/vaadin/app/CustomerFormDesign.html[the final state] to your own .html file.
-
- At this point we only have a static mockup of the actual UI. To implement a
- functional form component, we need some Java code as well. Vaadin Designer
- automatically creates a similarly named Java class, but a good habit is to never touch the auto-generated file, in this case the
- CustomerFormDesign.java file. If you'd introduce a new field to your form,
- your changes to CustomerFormDesign would be overridden by the tooling. Instead,
- we'll create a class called CustomerForm which inherits from the auto-generated
- CustomerFormDesign class.
-
- Start by creating a new Java class with the name CustomerForm. In Eclipse, right
- click on the "my.vaadin.app" package and choose menu:New[Class]. Type in the
- name _CustomerForm_, define the superclass as
- _my.vaadin.app.CustomerFormDesign_ and click _finish_.
-
- From the superclass, we inherit all the UI elements that we named when using
- the designer. E.g. by simply referencing to "save" field in the CustomerForm,
- we'll have access to the save button we previously created.
-
- We will later need a reference to the currently edited Customer object,
- CustomerService and the MyUI that uses this class. Add these fields and a
- basic constructor that accepts MyUI as a parameter to the CustomerForm class:
-
- [source,java]
- ----
- CustomerService service = CustomerService.getInstance();
- private Customer customer;
- private MyUI myUI;
-
- public CustomerForm(MyUI myUI) {
- this.myUI = myUI;
- }
- ----
-
- Although the form is not yet fully functional, you might want to see what it
- looks like at this point. Add it as a field to the _MyUI_ class:
-
- [source,java]
- ----
- CustomerForm form = new CustomerForm(this);
- ----
-
- Now let's modify the init method in MyUI to show the form. Let's wrap both the
- Grid and the CustomerForm in a horizontal layout and configure the Grid to use
- all of the available space more efficiently. Replace the line
- *layout.addComponents(filtering, grid);* with the following:
-
- [source,java]
- ----
- HorizontalLayout main = new HorizontalLayout(grid, form);
- main.setSpacing(true);
- main.setSizeFull();
- grid.setSizeFull();
- main.setExpandRatio(grid, 1);
-
- layout.addComponents(filtering, main);
- ----
-
- If you now save your changes and reload your application page in a browser,
- you should see your CustomerForm next to the grid that lists your
- existing entities.
-
- Let's get back to the CustomerForm. The first thing we'll need is to populate
- the options for the select. To add all enum values as valid selections, add the
- following line to the constructor:
-
- [source,java]
- ----
- status.addItems(CustomerStatus.values());
- ----
-
- Let's also improve the UX a bit. When building the design, we already
- emphasized the save button with a ValoTheme.BUTTON_PRIMARY style name. Thus, it
- would be natural if the enter-key would do the same action as clicking the
- save button. Assign a keyboard shortcut to the save button with this line in the
- constructor:
-
- [source,java]
- ----
- 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
- class and hit autocomplete (kbd:[Ctrl+Space]) and Eclipse will create a method
- stub for you. Complete it with the following implementation:
-
- [source,java]
- ----
- public void setCustomer(Customer customer) {
- this.customer = customer;
- BeanFieldGroup.bindFieldsUnbuffered(customer, this);
-
- // Show delete button for only customers already in the database
- delete.setVisible(customer.isPersisted());
- setVisible(true);
- firstName.selectAll();
- }
- ----
-
- 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.
-
- 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]
- annotation on fields to explicitly declare the edited property.
-
- We'll also want to ensure the form is visible and that focus goes to the
- firstName field to improve user experience. As we will be using the form to
- edit both new non-persisted objects and existing customers, we will also show
- the delete button only for customers that are already persisted in the backend.
-
- The last thing we need to do is to handle save and delete button clicks. Add
- the following methods to the CustomerForm class:
-
- [source,java]
- ----
- private void delete() {
- service.delete(customer);
- myUI.updateList();
- setVisible(false);
- }
-
- private void save() {
- service.save(customer);
- myUI.updateList();
- setVisible(false);
- }
- ----
-
- Finally, we'll add listeners to the buttons to call these methods. Adding these
- simple lambda expressions to the constructor will take care of that:
-
- [source,java]
- ----
- 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
- introduce an interface to replace the myUI field or, even better, use an event
- system like https://vaadin.com/wiki/-/wiki/main/Events+and+contexts[CDI events]
- to completely decouple the components. We'll leave that out of this tutorial for
- simplicity.
-
- === Creating a form using plain Java
-
- 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
- <<Connecting the form to the application>>.
-
- Start by creating a new Java class with the name CustomerForm. In Eclipse right
- click on the "my.vaadin.app" package and choose menu:New[Class]. Type in the
- name _CustomerForm_, define the superclass as _com.vaadin.ui.FormLayout_ and
- 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
- NativeSelect. Add the following field declarations and action buttons as Java
- fields to the CustomerForm:
-
- [source,java]
- ----
- 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 Button save = new Button("Save");
- private Button delete = new Button("Delete");
- ----
-
- Also, we will laterneed a reference to the currently edited Customer object,
- CustomerService and the MyUI that uses this class. Add these fields and a
- basic constructor that accepts MyUI as a parameter to the CustomerForm class:
-
- [source,java]
- ----
- private CustomerService service = CustomerService.getInstance();
- private Customer customer;
- private MyUI myUI;
-
- public CustomerForm(MyUI myUI) {
- this.myUI = myUI;
-
- setSizeUndefined();
- HorizontalLayout buttons = new HorizontalLayout(save, delete);
- buttons.setSpacing(true);
- addComponents(firstName, lastName, email, status, birthdate, buttons);
- }
- ----
-
- In the constructor we make the form size undefined, which practically means it
- will consume the minimum space defined by its content. Then we'll just add all
- the fields to the CustomerForm and add action buttons to the bottom - side-by-side
- using a HorizontalLayout. Although the form is not yet fully functional, you
- might want to see what it looks like at this point. Add it as a field to the MyUI
- class:
-
- [source,java]
- ----
- CustomerForm form = new CustomerForm(this);
- ----
-
- Now let's modify the init method in MyUI to show the form. Let's wrap both the
- Grid and the CustomerForm in a horizontal layout and configure the Grid to use
- all of the available space more efficiently. Replace the line
- *layout.addComponents(filtering, grid);* with the following:
-
- [source,java]
- ----
- HorizontalLayout main = new HorizontalLayout(grid, form);
- main.setSpacing(true);
- main.setSizeFull();
- grid.setSizeFull();
- main.setExpandRatio(grid, 1);
-
- layout.addComponents(filtering, main);
- ----
-
- When you now save your changes and reload your application page in your browser,
- you should see your CustomerForm next to the grid that lists your
- existing entities.
-
- Let's get back to the CustomerForm. The first thing we'll need is to populate
- the options for the select. To add all enum values as valid selections, add the
- following line to the constructor:
-
- [source,java]
- ----
- status.addItems(CustomerStatus.values());
- ----
-
- Let's also improve the UX a bit. The most common thing your users will want to
- do with this kind of form is to save it. Let's decorate the button with a style
- name that makes it more prominent in the UI and give it a keyboard shortcut -
- simply an enter hit in this case:
-
- [source,java]
- ----
- save.setStyleName(ValoTheme.BUTTON_PRIMARY);
- 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
- class and hit autocomplete (kbd:[Ctrl+Space]) and Eclipse will create a method
- stub for you. Complete it with the following implementation:
-
- [source,java]
- ----
- public void setCustomer(Customer customer) {
- this.customer = customer;
- BeanFieldGroup.bindFieldsUnbuffered(customer, this);
-
- // Show delete button for only customers already in the database
- delete.setVisible(customer.isPersisted());
- setVisible(true);
- firstName.selectAll();
- }
- ----
-
- 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.
-
- 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]
- 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
- firstName field to improve the user experience. As we will be using the form to
- edit both new non-persisted objects and existing customers, we will also show
- the delete button only for customers that are already persisted in the backend.
-
- The last thing we need to do is to handle save and delete button clicks. Add
- the following methods to the CustomerForm class:
-
- [source,java]
- ----
- private void delete() {
- service.delete(customer);
- myUI.updateList();
- setVisible(false);
- }
-
- private void save() {
- service.save(customer);
- myUI.updateList();
- setVisible(false);
- }
- ----
-
- Finally, we'll add listeners to the buttons to call these methods. Adding these
- simple lambda expressions to the constructor will take care of that:
-
- [source,java]
- ----
- 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
- introduce an interface to replace the myUI field or, event better, use an event
- system like https://vaadin.com/wiki/-/wiki/main/Events+and+contexts[CDI events]
- to completely decouple the components. We'll leave that out of this tutorial for
- simplicity.
-
- == Connecting the form to the application
-
- 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].
-
- 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
- customers and creating new ones.
-
- In the previous part, we already added the form to the _MyUI_ to see what it looks
- like. By default, we want it to be invisible, so let's first hide it
- by adding this line to the _init_ method of MyUI class:
-
- [source,java]
- ----
- form.setVisible(false);
- ----
-
- To edit the customer chosen from the Grid, add the following selection listener to
- the end of the _init_ method:
-
- [source,java]
- ----
- grid.addSelectionListener(event -> {
- if (event.getSelected().isEmpty()) {
- form.setVisible(false);
- } else {
- Customer customer = (Customer) event.getSelected().iterator().next();
- form.setCustomer(customer);
- }
- });
- ----
-
- In the listener, we simply take the Customer object of the selected row and pass it to
- the CustomerForm for editing. In the previous step, we added a side effect to the
- _setCustomer_ method that will bind the domain object to the corresponding fields
- and make it visible. If the selection is empty, we'll hide the form.
-
- To allow users to also create new customer records, we'll create a simple "Add
- customer button" to the top of the UI, right next to the _filtering_ composition
- we have already built from a CssLayout, a TextField and a Button. Introduce the new
- Button with a click listener, by adding the following lines to the _init_ method,
- right after where you introduced the _filtering_ composition:
-
- [source,java]
- ----
- Button addCustomerBtn = new Button("Add new customer");
- addCustomerBtn.addClickListener(e -> {
- grid.select(null);
- form.setCustomer(new Customer());
- });
- ----
-
- In the click listener, we first clear a possible selection from the grid and then
- instantiate a new Customer object and pass that to the form for editing.
-
- To add it beside our _filtering_ composition, we can use a HorizontalLayout to
- create a toolbar where we place both components. First, introduce a toolbar like
- 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
- toolbar instead of just the filtering composition, which we just moved to the
- _toolbar_ layout.
-
- [source,java]
- ----
- layout.addComponents(toolbar, main);
- ----
-
- All planned features are now done. You can save the changes and play around with
- the application. If something went wrong, you can also download an example of
- https://github.com/vaadin/tutorial[the final application] and see what went wrong.
-
- == It works! What next?
-
- Congratulations! Users can now create, read, update and delete customer records
- stored in the demo backend and you have completed creating your first CRUD UI
- with Vaadin.
-
- If you are an experienced Java developer, you are probably already full of ideas of
- how you can use your existing skills and create new shiny web UIs for your
- existing Java apps. If you want more ideas of how to create full stack
- applications, you might, for example, go through the
- http://spring.io/guides/gs/crud-with-vaadin/[Creating CRUD UI with Vaadin] guide
- and create a bit similar UI with a real database backend implemented with Spring
- Data JPA. We have also collected a couple of other resources for an easy
- start in your Vaadin developer career.
-
- * https://vaadin.com/docs/-/part/framework/introduction/intro-overview.html[Vaadin online documentation]
- * http://spring.io/guides/gs/crud-with-vaadin/[Creating CRUD UI with Vaadin] - the tutorial for your first Vaadin application using a Spring based backend.
- * https://github.com/mstahv/jpa-invoicer[Jave EE example app] - a Vaadin app example for creating invoices that uses Java EE backend, Apache DeltaSpike Data for simple JPA layer, OAuth2 based login, PDF generation etc.
- * http://vaadin.com/directory[Directory] - a vast source of awesome Vaadin add-ons
-
|