You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tutorial.adoc 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. :experimental:
  2. :sectnums:
  3. :imagesdir: img
  4. = Vaadin tutorial
  5. This tutorial gives you an overview of how you can use
  6. https://vaadin.com/framework[Vaadin Framework] to build single-page web UI's for your Java
  7. application. All you need to start with it is JDK 8 and an https://en.wikipedia.org/wiki/Integrated_development_environment[IDE] like Eclipse.
  8. No extensive knowledge of Java is even needed to get started, only the basic programming skills are required. Although the tutorial is built for
  9. Eclipse users, you can use your IDE of choice.
  10. We'll build a simple customer management system. It is not a real app, but we'll
  11. use an in-memory "backend" so that you can understand how to hook it to an
  12. existing Java based backend. We'll cover the basic Vaadin development and you
  13. can use the result as a basis for more experiments with Vaadin, like using
  14. add-ons, your own custom look and feel (aka. theme), adding new views or optimizing the result for
  15. mobile support.
  16. You'll need about 20 - 60 minutes to complete the tutorial, depending on your
  17. existing experience, but naturally you can just do the beginning of
  18. the exercise or pick any of the steps you want. To start from a specific step,
  19. we have prepared the example code after each step to be
  20. downloaded as a zip file. If don't want to do the exercise at all, you can also
  21. just https://github.com/vaadin/tutorial/[downlood the final application] and
  22. play around with it.
  23. The tutorial uses Java 8, so ensure you have an up-to-date JDK 8 installed. Most
  24. linux distributions can use package managers to install JDK8, Windows and Mac users should
  25. download it from
  26. http://www.oracle.com/technetwork/java/javase/downloads/index.html[Oracle's Java
  27. SE site].
  28. Also make sure you have the latest version of your IDE. Eclipse is available in
  29. various packages, be sure to download the *Eclipse IDE for Java EE Developers*
  30. from http://www.eclipse.org/downloads/[eclipse.org].
  31. == Creating a project using an archetype
  32. As a starting point for the application, we'll use a Maven archetype called
  33. vaadin-archetype-application. Maven archetypes are project stubs with basic
  34. build script and some example code.
  35. Start by choosing menu:File[New > Maven Project] from the menu.
  36. image::createMavenProject.jpg[Create a new Maven built Vaadin project.]
  37. TIP: If the "Maven Project" is not visible in the menu, you should switch to the
  38. _Java EE_ perspective. Use the shortcut button in the toolbar or
  39. menu:Window[Perspective] to do this.
  40. The first page in the wizard is ok with its defaults, but on the second page
  41. you'll need to choose _vaadin-archetype-application_ archetype. You can first
  42. try to find it using the filtering function, but in some cases Eclipse hasn't
  43. yet indexed the archetype catalog, so you might need to manually add the
  44. archetype details with the _Add Archetype_ button. The Group Id is _com.vaadin_,
  45. the Artifact Id is _vaadin-archetype-application_ and as a version you can use
  46. the latest Vaadin version, at the time of writing _7.6.2_. The _Repository URL_
  47. can be left blank.
  48. CAUTION: Eclipse has a bug in its project wizard. If
  49. _vaadin-archetype-application_ doesn't appear in the listing, even though you
  50. added it using the _Add Archetype_ button, close the whole new project wizard
  51. and re-open it by selecting menu:File[New > Maven Project] again. The archetype
  52. then typically appears in the listing and can be found by the filtering
  53. functionality.
  54. On the next wizard page, type in _my.vaadin_ as the Group Id, _app_ as the
  55. Artifact Id and click _Finish_. If this is your first Vaadin app, creating
  56. a project might take a while, depending on the speed of your network, as Vaadin
  57. libraries and other dependencies are being downloaded. Maven caches these on
  58. your local file system and creating your next Maven based Vaadin project will be much
  59. faster.
  60. Right click on the newly created project and choose menu:Run as[Maven Install].
  61. This will initiate a full build of your application and will finally create a
  62. https://en.wikipedia.org/wiki/WAR_(file_format)[war] file to the "target" directory that you can deploy to your application
  63. server. As Maven might again need to download some new modules and the project
  64. has a setup for add-on usage and contains a project specific theme, the first
  65. build will take a while.
  66. TIP: For the Maven compilation to work you need a JDK to be configured in your
  67. Eclipse in menu:Window[Preferences > Java > Installed JREs > Add...]. This step
  68. is necessary at least on Windows, if you are using a fresh installation of
  69. Eclipse or for some other reason haven't configured a JDK to your Eclipse. The
  70. JDK by default installs to _\Program Files\Java_ on Windows. You
  71. can make JDK the default JRE for your Eclipse.
  72. While the build is running, let's have a look at what the archetype created for
  73. you. You can browse your project resources from the tree structure in the
  74. _Project Explorer_. Maven's _pom.xml_ on top level contains settings for your
  75. projects build and declares the used dependencies. Open _Java Resources_ and
  76. below it _src/main/java_, the main source directory, and _my.vaadin.app_, the
  77. main Java package that will contain your Vaadin UI code.
  78. TIP: Eclipse shows all project files in the Project Explorer. In this case you
  79. can also find your _.java_ files via top level _src_ node, but the suggested
  80. method is to access them via the _Java Resources_ node, which is optimized for
  81. editing Java source code.
  82. The UI code (and the Servlet declaration) used by the application stub can be
  83. found in the _MyUI.java_ file. Let's read it through to see how it works. The
  84. _init_ method of a UI class is triggered when a user enters your web
  85. application. The VerticalLayout is one of the most used layout objects, which
  86. are used to position and display other Vaadin components in your UI classes. The
  87. example code creates one TextField to allow the user to input her name and a
  88. Button whose click listener dynamically adds a new Label component to the main
  89. layout. In the end of the init method we just configure the main layout and
  90. place components into it and set it to be the content of MyUI.
  91. To test your first Vaadin application, right click on the project and choose
  92. menu:Debug as[Maven build...]. The debug mode is slightly slower than the basic run
  93. mode, but it often helps you to figure out what is happening in your
  94. application.
  95. image::debugAsMavenBuild.jpg[Starting the server using a Maven target]
  96. In the dialog, type _Run in jetty_ to the _Name_ input and _jetty:run_ to the
  97. _Goals_ input.
  98. image::debugAsMavenBuild2.jpg[Generating a Maven launch for jetty:run target]
  99. Before clicking debug, to make sure debugging works properly, add your Java
  100. project to the source lookup path from the _Source_ tab, like it is being done
  101. in the image below.
  102. image::debugAsMavenBuildAddSources.jpg[Adding sources for debugging]
  103. Now click _Debug_ to continue. This will download a small Java web server
  104. (if not cached to your local Maven repository), and use it to host
  105. your application. Once the server has started, point your browser to the URL
  106. http://localhost:8080/[http://localhost:8080/] to see the running application.
  107. If you make changes to the code, the jetty server will notice the changes and in
  108. a couple of seconds most changes are automatically deployed. Reloading the page
  109. in your browser will show the changes.
  110. TIP: In some cases your JVM might not allow injecting changes on the fly. In
  111. these cases, Eclipse will complain about "Hot code replacement error". Just
  112. choose to restart the server to get the latest changes. Many Java developers use
  113. a commercial tool called http://zeroturnaround.com/software/jrebel/[JRebel] to make code
  114. replacement work better.
  115. Mastering the usage of the java debugger is also handy to better understand how your
  116. application actually works and fixing bugs that all developers write at some
  117. 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
  118. following line in the click listener:
  119. [source,java]
  120. ----
  121. layout.addComponent(new Label("Thanks " + name.getValue()
  122. ----
  123. This will add a breakpoint to the selected line. If you then click the button in
  124. your browser, the execution of the application will stop on that line. Eclipse
  125. will ask you to enter to _Debugging perspective_ and you can inspect its
  126. variables and step through the execution. Clicking on the _play_ icon in the
  127. toolbar will continue the execution. Double click the same line again to remove
  128. the breakpoint.
  129. image::debugInBreakPointVariable.jpg[Execution in a break point in the button click listener]
  130. Clicking the red square in the Console view will terminate the server process.
  131. You can restart it easily form the run/debug history. You can find that from the
  132. small down arrow next to the green play button or bug button (for the debug
  133. mode) in the toolbar. Alternatively you can use the main menu menu:Run[Run
  134. history/Debug history > Run in Jetty].
  135. To get back to the _Java EE Perspective_, an Eclipse mode designed for editing
  136. Java web app code, click the _Java EE_ button in the toolbar.
  137. == Adding a demo "backend"
  138. Before getting more into real Vaadin development, let's introduce some domain
  139. objects and a "fake backend". In a real world application, you'll most likely
  140. have something similar, implemented with, for example, JPA and EJB or a Spring based
  141. service.
  142. Copy the following three classes from github to your project. Class names
  143. point to the classes hosted in Github. Copying classes can be done in many ways.
  144. TIP: The fastest way to copy classes using Eclipse is to use your good old
  145. clipboard. Select the text content of the whole class from your browser, choose
  146. menu:Edit[Copy], focus the node representing the _my.vaadin.app_ Java package in
  147. Eclipse's Java Resources view and choose menu:Edit[Paste]. Eclipse is smart
  148. enough to automatically create a properly named Java file for the class.
  149. * https://raw.githubusercontent.com/vaadin/tutorial/master/src/main/java/my/vaadin/app/CustomerStatus.java[CustomerStatus] - this is a simple enum class
  150. * 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
  151. using in our example
  152. * 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.
  153. In the next steps, we'll be using these classes and build a UI around them. The
  154. actual implementation of these classes is not relevant for this tutorial, but
  155. feel free to have a look around.
  156. == Listing entities in a Grid
  157. 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].
  158. Often when you start building a UI for a data centric application, the first
  159. thing you want to do is to list your data from your backend. There are several
  160. components and methods in Vaadin to do this. In this example, we'll use the Grid
  161. component for tabular presentation of our customers.
  162. We'll start by introducing a Grid field to the MyUI class. We could of course
  163. just introduce the Grid as a variable in the init method, but we'll most likely
  164. want to refer to it later. Also, let's get a reference to the CustomerService.
  165. [source,java]
  166. ----
  167. public class MyUI extends UI {
  168. // Add next two lines:
  169. private CustomerService service = CustomerService.getInstance();
  170. private Grid grid = new Grid();
  171. // the rest is already there...
  172. @Override
  173. protected void init(VaadinRequest vaadinRequest) {
  174. ----
  175. TIP: If you are new to Java development, you probably don't feel comfortable
  176. with the red compilation error for the line where the Grid got introduced, due
  177. to a missing import. This is easily fixed in Eclipse by using the
  178. menu:Source[Organize Imports] command. Learn its shortcut (kbd:[Ctrl-Shift-O] or
  179. kbd:[CMD-Shift-O] on Macs), you'll be using it a lot in Java development. In
  180. possible class name collisions, always choose the appropriate class from the
  181. _com.vaadin.ui_ package if you want to import core Vaadin UI classes like the
  182. Grid.
  183. To simply list all properties of all Customer objects from the backend service,
  184. replace the init method with the following snippet:
  185. [source,java]
  186. ----
  187. @Override
  188. protected void init(VaadinRequest vaadinRequest) {
  189. final VerticalLayout layout = new VerticalLayout();
  190. // add Grid to the layout
  191. layout.addComponents(grid);
  192. // fetch list of Customers from service and assign it to Grid
  193. List<Customer> customers = service.findAll();
  194. grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers));
  195. layout.setMargin(true);
  196. setContent(layout);
  197. }
  198. ----
  199. TIP: Again, use the organize imports feature. The List object we use here is
  200. _java.util.List_.
  201. As we'll want to refresh the listing from various places in our application,
  202. extract the customer listing part into its own "updateList" method with the
  203. *public* modifier. The public modifier is handy later when we want to update the
  204. listing from other classes. You can let Eclipse help here by selecting the
  205. relevant lines and using the "quick fix" feature (kbd:[Ctrl+1] or kbd:[Cmd+1] on
  206. Macs). The extracted method call looks like this:
  207. [source,java]
  208. ----
  209. public void updateList() {
  210. List<Customer> customers = service.findAll();
  211. grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers));
  212. }
  213. ----
  214. If you try the application now, you'll see that quite many properties of the
  215. customers are shown in the grid. To limit the visible properties, configure
  216. the Grid using the _setColumns_ method to only show "firstName", "lastName" and
  217. "email" properties.
  218. [source,java]
  219. ----
  220. grid.setColumns("firstName", "lastName", "email");
  221. ----
  222. At this point the body of the MyUI class should look like this (servlet declaration
  223. omitted):
  224. [source,java]
  225. ----
  226. private CustomerService service = CustomerService.getInstance();
  227. private Grid grid = new Grid();
  228. @Override
  229. protected void init(VaadinRequest vaadinRequest) {
  230. final VerticalLayout layout = new VerticalLayout();
  231. grid.setColumns("firstName", "lastName", "email");
  232. // add Grid to the layout
  233. layout.addComponent(grid);
  234. updateList();
  235. layout.setMargin(true);
  236. setContent(layout);
  237. }
  238. public void updateList() {
  239. // fetch list of Customers from service and assign it to Grid
  240. List<Customer> customers = service.findAll();
  241. grid.setContainerDataSource(new BeanItemContainer<>(Customer.class, customers));
  242. }
  243. ----
  244. You can now save your changes to the file and verify the changes from your browser.
  245. You can do this at any point during the rest of the tutorial as well.
  246. == Creating live filtering for entities
  247. 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].
  248. A search functionality is expected in every modern application and it is
  249. also a nice Vaadin development exercise. Let's add a filtering functionality to
  250. the Customer listing we created in the previous step.
  251. We'll start by introducing a TextField component as a field to our UI class:
  252. [source,java]
  253. ----
  254. private TextField filterText = new TextField();
  255. ----
  256. In the _init_ method, configure the text field to contain a helpful input prompt
  257. and add a text change listener to the field. The exact place of these lines is
  258. not important, but add them, for example, after you have introduced the _layout_
  259. object.
  260. [source,java]
  261. ----
  262. filterText.setInputPrompt("filter by name...");
  263. filterText.addTextChangeListener(e -> {
  264. grid.setContainerDataSource(new BeanItemContainer<>(Customer.class,
  265. service.findAll(e.getText())));
  266. });
  267. ----
  268. TIP: To keep your code more readable, you can use autoformat after you write or
  269. copy paste code snippets. The default keyboard shortcut in Eclipse is
  270. kbd:[Ctrl+Shift+F] or kbd:[Cmd+Shift+F]
  271. The text change listener is another listener (in addition to the more commonly
  272. used ValueChangeListener) you can use with text fields in Vaadin. It is fired
  273. lazily while the user is typing, but only when there is a small pause in the
  274. typing. This makes it perfect for this kind of automatic filtering. When the
  275. user has changed the text, we'll just update the listing like in the updateList
  276. method, but use the current text as a filter for entries.
  277. To keep the _updateList_ method functional, it should also take into
  278. consideration the possible value in the filterText field. Change the line for
  279. fetching the customers into this:
  280. [source,java]
  281. ----
  282. List<Customer> customers = service.findAll(filterText.getValue());
  283. ----
  284. Before adding the text field to the UI, let's improve the usability a bit
  285. and make a short exercise to compose better components from lower level UI
  286. components. The search field can naturally be cleared with the keyboard, but let's
  287. add a clear button next to the text field. Start by adding the following lines
  288. to the init method, for example right after your filterText configuration:
  289. [source,java]
  290. ----
  291. Button clearFilterTextBtn = new Button(FontAwesome.TIMES);
  292. clearFilterTextBtn.setDescription("Clear the current filter");
  293. clearFilterTextBtn.addClickListener(e -> {
  294. filterText.clear();
  295. updateList();
  296. });
  297. ----
  298. Vaadin contains a set of built in icons, from which we use the "X" icon,
  299. _FontAwesome.TIMES_, here, which most users will recognise as a functionality to clear
  300. the value. If we set the description to a component, it will be shown as a
  301. tooltip for those users who hover the cursor over the button and wonder what to
  302. do with it. In the click listener, we simply clear the text from the field and
  303. refresh the content of the listing.
  304. Vaadin contains lots of different kinds of layouts. The simplest way to align
  305. the text field and the button next to each other would be to use a
  306. HorizontalLayout. An alternative way we use here is using a CssLayout, which is
  307. a lightweight layout that is easy to customize with css. Even if you wouldn't
  308. want to play with CSS yourself, you can often use one of the existing style
  309. rules in the default _Valo_ theme. The following snippet will create a nice
  310. compact "composition" of both the TextField and the clear button. Add these
  311. lines to the init method right after you configured the _clearFilterTextBtn_:
  312. [source,java]
  313. ----
  314. CssLayout filtering = new CssLayout();
  315. filtering.addComponents(filterText, clearFilterTextBtn);
  316. filtering.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
  317. ----
  318. Finally, *change* the row in the init method that currently adds only the grid,
  319. to add both _filtering_ composition and the _grid_ to the main _layout_ of the
  320. application.
  321. [source,java]
  322. ----
  323. layout.addComponents(filtering, grid);
  324. ----
  325. Now it is a good place to save your changes and try them in your browser.
  326. == Creating a form to edit Customer objects
  327. To edit and add Customer objects we need to create a form, that edits the
  328. values in our domain objects. This tutorial has two alternative methods to do
  329. that. Pick either of them.
  330. === Creating a form using Vaadin Designer
  331. 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].
  332. The form to edit Customer objects can be built using several methods of which
  333. the visual composition by drag 'n' drop is the most intuitive. Vaadin
  334. Designer is an Eclipse plugin that you can install and do WYSIWYG editing of
  335. your view code. We'll use it to create the form and then hook the editing logic
  336. to it with Java.
  337. TIP: If you are using another IDE or just prefer to compose your user interface
  338. with code, take the alternative step, <<Creating a form using plain Java>>,
  339. where the CustomerForm is composed using plain Java code.
  340. ==== Installing Vaadin Designer
  341. Vaadin Designer comes as an integrated part of Vaadin Plugin for Eclipse. It can
  342. be installed easily via Eclipse Marketplace. Choose menu:Help[Eclipse Marketplace]
  343. In the dialog, just search for Vaadin and click _install_ to mark it for
  344. installation. Clicking _Install Now_ will take you to choose the modules you want
  345. and accept the license agreement.
  346. image::pluginEclipseMarketPlace2.jpg[Selecting Vaadin Plugin for Eclipse for installation in Eclipse Marketplace]
  347. If you get a security warning about the software containing unsigned content,
  348. just accept the warning by clicking OK. After installation, Eclipse asks if you
  349. want to restart. Click Yes.
  350. TIP: When you use Vaadin Designer for the first time in the next
  351. step, it will ask for a license key. Get a key from
  352. https://vaadin.com/designer. If you are not willing to buy a license now, just
  353. acquire a trial license.
  354. ==== Creating the form design
  355. The following screencast will show you how to produce the
  356. _CustomerFormDesign.html_, a design file we need in this tutorial. Use pause and
  357. slow motion to follow better what is being done in the video. Feel free to get creative!
  358. video::B5dN69NSS78[youtube, width="640", height="400"]
  359. TIP: At any point of the process, you can also switch to the markup mode where
  360. you can edit the raw content of the .html file. If you wish to take a shortcut
  361. or think you did something wrong when using the designer, you can just
  362. 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.
  363. At this point we only have a static mockup of the actual UI. To implement a
  364. functional form component, we need some Java code as well. Vaadin Designer
  365. automatically creates a similarly named Java class, but a good habit is to never touch the auto-generated file, in this case the
  366. CustomerFormDesign.java file. If you'd introduce a new field to your form,
  367. your changes to CustomerFormDesign would be overridden by the tooling. Instead,
  368. we'll create a class called CustomerForm which inherits from the auto-generated
  369. CustomerFormDesign class.
  370. Start by creating a new Java class with the name CustomerForm. In Eclipse, right
  371. click on the "my.vaadin.app" package and choose menu:New[Class]. Type in the
  372. name _CustomerForm_, define the superclass as
  373. _my.vaadin.app.CustomerFormDesign_ and click _finish_.
  374. From the superclass, we inherit all the UI elements that we named when using
  375. the designer. E.g. by simply referencing to "save" field in the CustomerForm,
  376. we'll have access to the save button we previously created.
  377. We will later need a reference to the currently edited Customer object,
  378. CustomerService and the MyUI that uses this class. Add these fields and a
  379. basic constructor that accepts MyUI as a parameter to the CustomerForm class:
  380. [source,java]
  381. ----
  382. CustomerService service = CustomerService.getInstance();
  383. private Customer customer;
  384. private MyUI myUI;
  385. public CustomerForm(MyUI myUI) {
  386. this.myUI = myUI;
  387. }
  388. ----
  389. Although the form is not yet fully functional, you might want to see what it
  390. looks like at this point. Add it as a field to the _MyUI_ class:
  391. [source,java]
  392. ----
  393. CustomerForm form = new CustomerForm(this);
  394. ----
  395. Now let's modify the init method in MyUI to show the form. Let's wrap both the
  396. Grid and the CustomerForm in a horizontal layout and configure the Grid to use
  397. all of the available space more efficiently. Replace the line
  398. *layout.addComponents(filtering, grid);* with the following:
  399. [source,java]
  400. ----
  401. HorizontalLayout main = new HorizontalLayout(grid, form);
  402. main.setSpacing(true);
  403. main.setSizeFull();
  404. grid.setSizeFull();
  405. main.setExpandRatio(grid, 1);
  406. layout.addComponents(filtering, main);
  407. ----
  408. If you now save your changes and reload your application page in a browser,
  409. you should see your CustomerForm next to the grid that lists your
  410. existing entities.
  411. Let's get back to the CustomerForm. The first thing we'll need is to populate
  412. the options for the select. To add all enum values as valid selections, add the
  413. following line to the constructor:
  414. [source,java]
  415. ----
  416. status.addItems(CustomerStatus.values());
  417. ----
  418. Let's also improve the UX a bit. When building the design, we already
  419. emphasized the save button with a ValoTheme.BUTTON_PRIMARY style name. Thus, it
  420. would be natural if the enter-key would do the same action as clicking the
  421. save button. Assign a keyboard shortcut to the save button with this line in the
  422. constructor:
  423. [source,java]
  424. ----
  425. save.setClickShortcut(KeyCode.ENTER);
  426. ----
  427. To finish our form, we need to create a public API that we will use in the next
  428. part from MyUI, to pass in a Customer object that the form should edit. We
  429. will also add some logic to actually save the changes. We'll start by creating a
  430. setter method to the Customer field. Just type _setCus_ in the body of the
  431. class and hit autocomplete (kbd:[Ctrl+Space]) and Eclipse will create a method
  432. stub for you. Complete it with the following implementation:
  433. [source,java]
  434. ----
  435. public void setCustomer(Customer customer) {
  436. this.customer = customer;
  437. BeanFieldGroup.bindFieldsUnbuffered(customer, this);
  438. // Show delete button for only customers already in the database
  439. delete.setVisible(customer.isPersisted());
  440. setVisible(true);
  441. firstName.selectAll();
  442. }
  443. ----
  444. In addition to saving the reference of the currently edited Customer object, we are
  445. calling the _BeanFieldGroup.bindFieldsUnbuffered_ method. It will initialize all
  446. similarly named editor fields in this form with the values from their
  447. counterpart in the given Customer object. Also, it will automatically update the
  448. values in the domain objects as the corresponding field value changes in the
  449. user interface.
  450. TIP: If the naming convention based databinding doesn't fit your needs, you
  451. can use
  452. https://www.vaadin.com/api/com/vaadin/data/fieldgroup/PropertyId.html[PropertyId]
  453. annotation on fields to explicitly declare the edited property.
  454. We'll also want to ensure the form is visible and that focus goes to the
  455. firstName field to improve user experience. As we will be using the form to
  456. edit both new non-persisted objects and existing customers, we will also show
  457. the delete button only for customers that are already persisted in the backend.
  458. The last thing we need to do is to handle save and delete button clicks. Add
  459. the following methods to the CustomerForm class:
  460. [source,java]
  461. ----
  462. private void delete() {
  463. service.delete(customer);
  464. myUI.updateList();
  465. setVisible(false);
  466. }
  467. private void save() {
  468. service.save(customer);
  469. myUI.updateList();
  470. setVisible(false);
  471. }
  472. ----
  473. Finally, we'll add listeners to the buttons to call these methods. Adding these
  474. simple lambda expressions to the constructor will take care of that:
  475. [source,java]
  476. ----
  477. save.addClickListener(e->this.save());
  478. delete.addClickListener(e->this.delete());
  479. ----
  480. TIP: For a truly re-usable form component in a real life project, you'd want to
  481. introduce an interface to replace the myUI field or, even better, use an event
  482. system like https://vaadin.com/wiki/-/wiki/main/Events+and+contexts[CDI events]
  483. to completely decouple the components. We'll leave that out of this tutorial for
  484. simplicity.
  485. === Creating a form using plain Java
  486. This is an alternative step to the <<Creating a form using Vaadin Designer>>,
  487. where you'll build the form UI programmatically in plain Java. If you already
  488. completed the step using Vaadin Designer, you can proceed to
  489. <<Connecting the form to the application>>.
  490. Start by creating a new Java class with the name CustomerForm. In Eclipse right
  491. click on the "my.vaadin.app" package and choose menu:New[Class]. Type in the
  492. name _CustomerForm_, define the superclass as _com.vaadin.ui.FormLayout_ and
  493. click _finish_.
  494. In the form, we'll need editor fields for each property in our Customer domain
  495. class. There are different kinds of fields in Vaadin for editing different kinds
  496. of properties. In this example, we'll use a TextField, a PopupDateField and a
  497. NativeSelect. Add the following field declarations and action buttons as Java
  498. fields to the CustomerForm:
  499. [source,java]
  500. ----
  501. private TextField firstName = new TextField("First name");
  502. private TextField lastName = new TextField("Last name");
  503. private TextField email = new TextField("Email");
  504. private NativeSelect status = new NativeSelect("Status");
  505. private PopupDateField birthdate = new PopupDateField("Birthday");
  506. private Button save = new Button("Save");
  507. private Button delete = new Button("Delete");
  508. ----
  509. Also, we will laterneed a reference to the currently edited Customer object,
  510. CustomerService and the MyUI that uses this class. Add these fields and a
  511. basic constructor that accepts MyUI as a parameter to the CustomerForm class:
  512. [source,java]
  513. ----
  514. private CustomerService service = CustomerService.getInstance();
  515. private Customer customer;
  516. private MyUI myUI;
  517. public CustomerForm(MyUI myUI) {
  518. this.myUI = myUI;
  519. setSizeUndefined();
  520. HorizontalLayout buttons = new HorizontalLayout(save, delete);
  521. buttons.setSpacing(true);
  522. addComponents(firstName, lastName, email, status, birthdate, buttons);
  523. }
  524. ----
  525. In the constructor we make the form size undefined, which practically means it
  526. will consume the minimum space defined by its content. Then we'll just add all
  527. the fields to the CustomerForm and add action buttons to the bottom - side-by-side
  528. using a HorizontalLayout. Although the form is not yet fully functional, you
  529. might want to see what it looks like at this point. Add it as a field to the MyUI
  530. class:
  531. [source,java]
  532. ----
  533. CustomerForm form = new CustomerForm(this);
  534. ----
  535. Now let's modify the init method in MyUI to show the form. Let's wrap both the
  536. Grid and the CustomerForm in a horizontal layout and configure the Grid to use
  537. all of the available space more efficiently. Replace the line
  538. *layout.addComponents(filtering, grid);* with the following:
  539. [source,java]
  540. ----
  541. HorizontalLayout main = new HorizontalLayout(grid, form);
  542. main.setSpacing(true);
  543. main.setSizeFull();
  544. grid.setSizeFull();
  545. main.setExpandRatio(grid, 1);
  546. layout.addComponents(filtering, main);
  547. ----
  548. When you now save your changes and reload your application page in your browser,
  549. you should see your CustomerForm next to the grid that lists your
  550. existing entities.
  551. Let's get back to the CustomerForm. The first thing we'll need is to populate
  552. the options for the select. To add all enum values as valid selections, add the
  553. following line to the constructor:
  554. [source,java]
  555. ----
  556. status.addItems(CustomerStatus.values());
  557. ----
  558. Let's also improve the UX a bit. The most common thing your users will want to
  559. do with this kind of form is to save it. Let's decorate the button with a style
  560. name that makes it more prominent in the UI and give it a keyboard shortcut -
  561. simply an enter hit in this case:
  562. [source,java]
  563. ----
  564. save.setStyleName(ValoTheme.BUTTON_PRIMARY);
  565. save.setClickShortcut(KeyCode.ENTER);
  566. ----
  567. To finish our form, we need to create a public API that we will use in the next
  568. part from the MyUI, to pass in a Customer object that the form should edit. We
  569. will also add some logic to actually save the changes. We'll start by creating a
  570. setter method for the Customer field. Just type _setCus_ in the body of the
  571. class and hit autocomplete (kbd:[Ctrl+Space]) and Eclipse will create a method
  572. stub for you. Complete it with the following implementation:
  573. [source,java]
  574. ----
  575. public void setCustomer(Customer customer) {
  576. this.customer = customer;
  577. BeanFieldGroup.bindFieldsUnbuffered(customer, this);
  578. // Show delete button for only customers already in the database
  579. delete.setVisible(customer.isPersisted());
  580. setVisible(true);
  581. firstName.selectAll();
  582. }
  583. ----
  584. In addition to saving the reference of the currently edited Customer object, we are
  585. calling _BeanFieldGroup.bindFieldsUnbuffered_ method. It will initialise all
  586. similarly named editor fields in this form with the values from their
  587. counterpart in the given Customer object. Also, it will automatically update the
  588. values in the domain objects as the corresponding field value changes in the
  589. user interface.
  590. TIP: If the naming convention based databinding doesn't fit your needs, you
  591. can use
  592. https://www.vaadin.com/api/com/vaadin/data/fieldgroup/PropertyId.html[PropertyId]
  593. annotation on fields to explicitly declare the edited property.
  594. We'll also want to ensure the form is visible and that the focus goes to the
  595. firstName field to improve the user experience. As we will be using the form to
  596. edit both new non-persisted objects and existing customers, we will also show
  597. the delete button only for customers that are already persisted in the backend.
  598. The last thing we need to do is to handle save and delete button clicks. Add
  599. the following methods to the CustomerForm class:
  600. [source,java]
  601. ----
  602. private void delete() {
  603. service.delete(customer);
  604. myUI.updateList();
  605. setVisible(false);
  606. }
  607. private void save() {
  608. service.save(customer);
  609. myUI.updateList();
  610. setVisible(false);
  611. }
  612. ----
  613. Finally, we'll add listeners to the buttons to call these methods. Adding these
  614. simple lambda expressions to the constructor will take care of that:
  615. [source,java]
  616. ----
  617. save.addClickListener(e->this.save());
  618. delete.addClickListener(e->this.delete());
  619. ----
  620. TIP: For a truly re-usable form component in a real life project, you'd want to
  621. introduce an interface to replace the myUI field or, event better, use an event
  622. system like https://vaadin.com/wiki/-/wiki/main/Events+and+contexts[CDI events]
  623. to completely decouple the components. We'll leave that out of this tutorial for
  624. simplicity.
  625. == Connecting the form to the application
  626. 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].
  627. In this part, we'll use the CustomerForm class, which we created in the
  628. previous step, from the MyUI class. We will use it for both editing the existing
  629. customers and creating new ones.
  630. In the previous part, we already added the form to the _MyUI_ to see what it looks
  631. like. By default, we want it to be invisible, so let's first hide it
  632. by adding this line to the _init_ method of MyUI class:
  633. [source,java]
  634. ----
  635. form.setVisible(false);
  636. ----
  637. To edit the customer chosen from the Grid, add the following selection listener to
  638. the end of the _init_ method:
  639. [source,java]
  640. ----
  641. grid.addSelectionListener(event -> {
  642. if (event.getSelected().isEmpty()) {
  643. form.setVisible(false);
  644. } else {
  645. Customer customer = (Customer) event.getSelected().iterator().next();
  646. form.setCustomer(customer);
  647. }
  648. });
  649. ----
  650. In the listener, we simply take the Customer object of the selected row and pass it to
  651. the CustomerForm for editing. In the previous step, we added a side effect to the
  652. _setCustomer_ method that will bind the domain object to the corresponding fields
  653. and make it visible. If the selection is empty, we'll hide the form.
  654. To allow users to also create new customer records, we'll create a simple "Add
  655. customer button" to the top of the UI, right next to the _filtering_ composition
  656. we have already built from a CssLayout, a TextField and a Button. Introduce the new
  657. Button with a click listener, by adding the following lines to the _init_ method,
  658. right after where you introduced the _filtering_ composition:
  659. [source,java]
  660. ----
  661. Button addCustomerBtn = new Button("Add new customer");
  662. addCustomerBtn.addClickListener(e -> {
  663. grid.select(null);
  664. form.setCustomer(new Customer());
  665. });
  666. ----
  667. In the click listener, we first clear a possible selection from the grid and then
  668. instantiate a new Customer object and pass that to the form for editing.
  669. To add it beside our _filtering_ composition, we can use a HorizontalLayout to
  670. create a toolbar where we place both components. First, introduce a toolbar like
  671. this after the previously created _addCustomerBtn_:
  672. [source,java]
  673. ----
  674. HorizontalLayout toolbar = new HorizontalLayout(filtering, addCustomerBtn);
  675. toolbar.setSpacing(true);
  676. ----
  677. And, again, *replace* the line that populates your main layout to add the
  678. toolbar instead of just the filtering composition, which we just moved to the
  679. _toolbar_ layout.
  680. [source,java]
  681. ----
  682. layout.addComponents(toolbar, main);
  683. ----
  684. All planned features are now done. You can save the changes and play around with
  685. the application. If something went wrong, you can also download an example of
  686. https://github.com/vaadin/tutorial[the final application] and see what went wrong.
  687. == It works! What next?
  688. Congratulations! Users can now create, read, update and delete customer records
  689. stored in the demo backend and you have completed creating your first CRUD UI
  690. with Vaadin.
  691. If you are an experienced Java developer, you are probably already full of ideas of
  692. how you can use your existing skills and create new shiny web UIs for your
  693. existing Java apps. If you want more ideas of how to create full stack
  694. applications, you might, for example, go through the
  695. http://spring.io/guides/gs/crud-with-vaadin/[Creating CRUD UI with Vaadin] guide
  696. and create a bit similar UI with a real database backend implemented with Spring
  697. Data JPA. We have also collected a couple of other resources for an easy
  698. start in your Vaadin developer career.
  699. * https://vaadin.com/docs/-/part/framework/introduction/intro-overview.html[Vaadin online documentation]
  700. * 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.
  701. * 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.
  702. * http://vaadin.com/directory[Directory] - a vast source of awesome Vaadin add-ons