1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
|
---
title: Vaadin Tutorial
order: 1
layout: page
subnav_auto_list_numbers: true
subnav:
- title: Overview
href: '#framework.tutorial.overview'
subnav:
- title: Installing the Development Tools
href: '#framework.tutorial.overview.tools'
- title: Creating a project using an archetype
href: '#framework.tutorial.archetype'
- title: Adding a demo "backend"
href: '#framework.tutorial.backend'
- title: Listing entities in a Grid
href: '#framework.tutorial.grid'
- title: Creating live filtering for entities
href: '#framework.tutorial.filtering'
- title: Creating a form to edit Customer objects
href: '#framework.tutorial.form'
subnav:
- title: Creating a form using Vaadin Designer
href: '#framework.tutorial.form.designer'
subnav:
- title: Installing Vaadin Designer
href: '#framework.tutorial.form.designer.install'
- title: Creating the form design
href: '#framework.tutorial.form.designer.create'
- title: Creating a form using plain Java
href: '#framework.tutorial.form.java'
- title: Connecting the form to the application
href: '#framework.tutorial.form-connection'
- title: It works! What next?
href: '#framework.tutorial.next'
---
:sectnums:
[[framework.tutorial]]
= Vaadin Tutorial
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.
No extensive knowledge of Java is needed, only basic programming skills are required.
[[framework.tutorial.overview]]
== Overview
You'll have your first Vaadin app running in your IDE in a couple of minutes. To complete the whole tutorial, you'll need about 20 to 60 minutes, depending on your existing experience.
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.
In this tutorial, we build a simple customer management system.
It is not a real application; we use an in-memory "back-end", so that you can understand how to hook it to an existing Java based back-end.
We cover the basic Vaadin development and you can use the result as a basis for more experiments with Vaadin, such as using add-ons, your own custom look-and- feel (aka. theme), adding new views, or optimizing the result for mobile support.
[[figure.framework.tutorial.final-ui]]
.UI to be built in the tutorial
image::img/finalUI.jpg[]
If you do not want to do the exercise at all, you can also just https://github.com/vaadin/tutorial/[download the final application] and play around with it.
TIP: In addition to this written tutorial, we have recorded the steps as https://www.youtube.com/playlist?list=PLcRrh9hGNalkZx921iMqZ-jXR0C72eIPR[a series of videos]. You can just watch all the videos or watch the video of each step before you do the same step yourself.
[[framework.tutorial.overview.tools]]
=== Installing the Development Tools
The tutorial uses Java 8, so please ensure that 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].
[[framework.tutorial.archetype]]
== Creating a Project from an Archetype
The following video shows how to do this step of the tutorial:
video::sMGHSK_97NI[youtube, width="640", height="400"]
As the starting point for the application, we use a Maven archetype called `vaadin-archetype-application`.
Archetypes are project stubs that have some example code and a basic Maven build script.
. Start by choosing "File > New > Maven Project" from the menu.
+
[[figure.framework.tutorial.create-maven-project]]
.Create a new Maven project
image::img/createMavenProject.jpg[width=70%]
+
TIP: If the [guilabel]#Maven Project# is not visible in the menu, you should switch to the _Java EE_ perspective.
You can use the shortcut button in the tool bar or "Window > Perspective" to switch to the perspective.
. The first step in the wizard is good as is for our purpose.
Just click [guibutton]#Next#.
. In the second step, you need to choose the `vaadin-archetype-application` archetype.
+
.Selecting the archetype
image::img/projectWizard2-top.jpg[width=70%]
+
You can first try to find it using the filtering function.
+
If Eclipse has not yet indexed the archetype catalog, you need to manually add the archetype details.
+
TIP: Some Eclipse installations do not automatically add Maven Central to the list of Maven catalogues, resulting in the Vaadin archetypes not being available in the wizard. To fix this, open Eclipse Preferences > Maven > Archetypes and select `Add Remote Catalog`. The URL to the Maven Central catalog file is `http://repo1.maven.org/maven2/archetype-catalog.xml`. After applying the changes, the Vaadin archetypes should be available in the wizard.
+
// +
// .Adding a new archetype
// image::img/projectWizard2-add.jpg[width=70%]
+
Click the [guibutton]#Add Archetype# button.
+
.Settings for a new archetype
image::img/projectWizardAddArchetype-crop.jpg[width=70%]
+
Enter the following values:
+
[guilabel]#Group ID#::
Give `com.vaadin`
[guilabel]#Artifact ID#::
Give `vaadin-archetype-application`
[guilabel]#Version#::
You can find the latest Vaadin version number from https://vaadin.com/framework/releases[vaadin.com/framework/releases].
[guilabel]#Repository URL#::
This can be left blank.
+
And click [guibutton]#OK#.
Now you can select the new archetype from the list.
+
WARNING: Eclipse has a bug in its project wizard.
The `vaadin-archetype-application` may not appear in the listing, even though you added it using the [guibutton]#Add Archetype# button.
If this occurs, close the whole new project wizard and re-open it by selecting "File > New > Maven Project" again.
The archetype then typically appears in the listing and can be found by the filtering functionality.
. In the next wizard step, type in the following fields:
[guilabel]#Group Id#:: `my.vaadin`
[guilabel]#Artifact Id#:: `app`
+
and click [guibutton]#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 them on your local file system.
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 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...".
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 [filename]#\Program Files\Java# on Windows.
You can make JDK the default JRE for your Eclipse.
While the build is running, let us have a look at what the archetype created for
you.
You can browse your project resources from the tree structure in the [guilabel]#Project Explorer#.
Maven's [filename]#pom.xml# on top level contains settings for building your project and declares the used dependencies.
Open [guilabel]#Java Resources# and below it [filename]#src/main/java#, the main source directory, and [packagename]#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 [filename]#.java# files from under the top-level [filename]#src# node.
However, the suggested method is to access them from under the [guilabel]#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 [filename]#MyUI.java# file.
Let us read it through to see how it works.
The [methodname]#init()# method of a UI class is triggered when a user enters your web application.
The [classname]#VerticalLayout# is one of the most used layout components, which
are used to position and display other Vaadin components in your UI classes.
The example code creates one [classname]#TextField# to allow the user to input her name and a [classname]#Button# whose click listener dynamically adds a new [classname]#Label# component to the main layout.
In the end of the [methodname]#init()# method, we just configure the main layout and place components into it and set it to be the content of [classname]#MyUI#.
To test your first Vaadin application, right-click on the project and choose "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.
[[figure.framework.tutorial.debug-as-maven-build]]
.Starting the server using a Maven target
image::img/debugAsMavenBuild.jpg[]
In the dialog, type `Run in jetty` to the [guilabel]#Name# input and `jetty:run` to the [guilabel]#Goals# input.
[[figure.framework.tutorial.jetty-run]]
.Generating a Maven launch for `jetty:run` target
image::img/debugAsMavenBuild2.jpg[]
Before clicking debug, to make sure debugging works properly, add your Java
project to the source lookup path from the [guilabel]#Source# tab, as it is being done in <<figure.tutorial.creating.add-sources>>.
[[figure.tutorial.creating.add-sources]]
.Adding sources for debugging
image::img/debugAsMavenBuildAddSources.jpg[]
Now click [guibutton]#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()));
----
Doing so adds 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_.
That way you can step through the execution and inspect the variables.
Clicking on the _play_ icon in the toolbar will continue the execution.
Double-click the same line again to remove the breakpoint.
[[figure.framework.tutorial.breakpoint]]
.Execution in a break point in the button click listener
image::img/debugInBreakPointVariable.jpg[]
Clicking the red square in the [guilabel]#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 tool bar.
Alternatively, you can use the main 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 [guibutton]#Java EE# button in the toolbar.
[[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 shows how to do this step of the tutorial:
video::qF31jkBFbR0[youtube, width="640", height="400"]
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
"Edit > Copy", focus the node representing the [packagename]#my.vaadin.app# Java package in Eclipse's Java Resources view and choose "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 will 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 [classname]#Customer# instances.
You can think of this as your entry point to your fake database.
In the next steps, we will 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.
[[framework.tutorial.grid]]
== Listing entities in a Grid
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.
There are several components and ways in Vaadin to do this.
In this example, we will use the Grid component for tabular presentation of our customers.
The following video shows how to do this step of the tutorial:
video::EBCm-Vf_fUs[youtube, width="640", height="400"]
We start by introducing a [classname]#Grid# to the [classname]#MyUI# class.
We could of course just introduce the Grid as a variable in the [methodname]#init()# method, but we most likely want to refer to it later.
Also, let us get a reference to the [classname]#CustomerService#.
[source,java]
----
public class MyUI extends UI {
// Add the next two lines:
private CustomerService service = CustomerService.getInstance();
private Grid<Customer> grid = new Grid<>(Customer.class);
// The rest is already there...
@Override
protected void init(VaadinRequest vaadinRequest) {
...
----
TIP: If you are new to Java development, you probably do not feel comfortable
with the red compilation error for the line where the [classname]#Grid# got introduced, because of 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.setItems(customers);
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.setItems(customers);
}
----
If you try the application now, you'll see an empty Grid with no columns. To add columns, configure
the Grid using the _setColumns_ method to show the "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<Customer> grid = new Grid<>(Customer.class);
@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();
setContent(layout);
}
public void updateList() {
// fetch list of Customers from service and assign it to Grid
List<Customer> customers = service.findAll();
grid.setItems(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.
[[framework.tutorial.filtering]]
== Creating live filtering for entities
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
the Customer listing we created in the previous step.
The following video shows how to do this step of the tutorial:
video::kyMaJLUtz3g[youtube, width="640", height="400"]
We'll start by introducing a [classname]#TextField# component as a field to our [classname]#UI# class:
[source,java]
----
private TextField filterText = new TextField();
----
In the [methodname]#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.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]
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 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(VaadinIcons.CLOSE);
clearFilterTextBtn.setDescription("Clear the current filter");
clearFilterTextBtn.addClickListener(e -> filterText.clear());
----
Vaadin contains a set of built in icons, from which we use the "X" icon,
_VaadinIcons.CLOSE_, 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.
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 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_:
[source,java]
----
CssLayout filtering = new CssLayout();
filtering.addComponents(filterText, clearFilterTextBtn);
filtering.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
----
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.
[source,java]
----
layout.addComponents(filtering, grid);
----
Now it is a good place to save your changes and try them in your browser.
[[framework.tutorial.form]]
== 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.
[[framework.tutorial.form.designer]]
=== Creating a form using Vaadin Designer
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
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.
[[framework.tutorial.form.designer.install]]
==== 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.
[[figure.framework.tutorial.plugin-install]]
.Selecting Vaadin Plugin for Eclipse for installation in Eclipse Marketplace
image::img/pluginEclipseMarketPlace2.jpg[]
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.
[[framework.tutorial.form.designer.create]]
==== 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::zLE2YfLB1MM[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.
TIP: With Vaadin Framework 8, make following things differently:
For status' NativeSelect Component, set Itemtype as CustomerStatus enum.
Use DateField Component for birthday, instead of PopupDateField.
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]
----
private 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]
----
private 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.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.setItems(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 adding a [classname]#Binder# as a field to the [classname]#CustomerForm# class:
[source,java]
----
private Binder<Customer> binder = new Binder<>(Customer.class);
----
In the constructor of the CustomerForm class add the following line to configure
the Binder:
[source,java]
----
binder.bindInstanceFields(this);
----
This configures the Binder 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:
[source,java]
----
public void setCustomer(Customer customer) {
this.customer = customer;
binder.setBean(customer);
// 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 _Binder.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]
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.
[[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
<<Connecting the form to the application>>.
The following video shows how to create a form using plain Java:
video::jOhkclbdwp0[youtube, width="640", height="400"]
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 DateField 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<CustomerStatus> status = new NativeSelect<>("Status");
private DateField birthdate = new DateField("Birthday");
private Button save = new Button("Save");
private Button delete = new Button("Delete");
----
Also, 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]
----
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);
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]
----
private 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.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.setItems(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 adding a
_Binder_ as a field to the _CustomerForm_ class:
[source,java]
----
private Binder<Customer> binder = new Binder<>(Customer.class);
----
In the constructor of the CustomerForm class add the following line to configure
the Binder:
[source,java]
----
binder.bindInstanceFields(this);
----
This configures the Binder 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:
[source,java]
----
public void setCustomer(Customer customer) {
this.customer = customer;
binder.setBean(customer);
// 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 _Binder.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/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
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, 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.
[[framework.tutorial.form-connection]]
== Connecting the form to the application
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
customers and creating new ones.
The following video shows how to do this step of the tutorial:
video::eMCWf3PfXLs[youtube, width="640", height="400"]
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.asSingleSelect().addValueChangeListener(event -> {
if (event.getValue() == null) {
form.setVisible(false);
} else {
form.setCustomer(event.getValue());
}
});
----
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.asSingleSelect().clear();
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);
----
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.
[[framework.tutorial.next]]
== 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]
* https://vaadin.com/full-stack-starter[Bakery App Starter for Vaadin Framework 8 and Spring] - A fully functional and tested full stack application for you to use as a starting point and a reference implementation on how business grade Vaadin applications should be made.
* 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
|