Full source code is up on [GitHub here]
(https://github.com/bitbythecron/vaadin-spring-example). I am playing with Vaadin 13 for the first time and am building a simple “Supers App” where you can CRUD super heroes/villains and their Powers. Just something fun to mess around with.
The main view/page for the app is ManagementView
which looks like this:
@Route(value = "")
public class ManagementView extends VerticalLayout {
private Tabs tabs;
private DataService dataService;
public ManagementView(DataService dataService) {
this.tabs = new Tabs();
this.dataService = dataService;
init();
}
private void init() {
// Supers Pain
HorizontalLayout supersPaneLayout = new HorizontalLayout();
supersPaneLayout.setMargin(true);
supersPaneLayout.setSizeFull();
TextField tfNickname = new TextField("Nickname");
tfNickname.setPlaceholder("e.g. \"Big Bear\"");
ListBox<String> lbSuperTypes = new ListBox<>();
lbSuperTypes.setItems("Hero", "Villain");
List<String> powers = dataService.fetchAllPowers();
VerticalLayout cbLayout = new VerticalLayout();
for (String power : powers) {
Checkbox cbPower = new Checkbox();
cbPower.setLabel(power);
cbLayout.add(cbPower);
}
Button btnAddSuper = new Button("Add", new Icon(VaadinIcon.PLUS));
btnAddSuper.addClickListener(new AddSuperClickListener(tfNickname, lbSuperTypes, cbLayout, dataService));
supersPaneLayout.add(tfNickname, lbSuperTypes, cbLayout, btnAddSuper);
ListBox<String> lbPowers = new ListBox<>();
lbPowers.setItems(powers);
lbPowers.setVisible(false);
Div masterDiv = new Div(supersPaneLayout, lbPowers);
Tab tbSupers = new Tab("Supers");
Tab tbPowers = new Tab("Powers");
tbSupers.setFlexGrow(2);
tbPowers.setFlexGrow(2);
Map<Tab, Component> tabsToPages = new HashMap<>();
tabsToPages.put(tbSupers, supersPaneLayout);
tabsToPages.put(tbPowers, lbPowers);
Set<Component> pagesShown = Stream.of(supersPaneLayout)
.collect(Collectors.toSet());
tabs.addSelectedChangeListener(event -> {
pagesShown.forEach(page -> page.setVisible(false));
pagesShown.clear();
Component selectedPage = tabsToPages.get(tabs.getSelectedTab());
selectedPage.setVisible(true);
pagesShown.add(selectedPage);
});
tabs.setFlexGrowForEnclosedTabs(2);
tabs.add(tbSupers, tbPowers);
setHorizontalComponentAlignment(Alignment.CENTER, tabs);
add(tabs);
add(masterDiv);
}
}
As you can see I’m injecting a DataService
whose abridged version looks like this:
@Component
public class DataService {
private Map<String,Super> supersMap;
private List<String> powersList;
public DataService() {
this.supersMap = new ConcurrentHashMap<>();
this.powersList = new ArrayList<>();
powersList.addAll(Arrays.asList(
"Flying",
"Invisibility",
"Super Strength",
"Super Speed",
"Fast Healing",
"Pyrotechnics",
"Cryotechnics",
"Electrotechnics"
));
}
public void createSuper(Super toCreate) {
if (!supersMap.containsKey(toCreate.getNickname())) {
supersMap.put(toCreate.getNickname(), toCreate);
System.out.println("New super added to the store!");
}
}
// ... some other methods down here
}
And this createSuper()
method is called from inside ManagementView
’s click listener whose code is:
@Override
public void onComponentEvent(ClickEvent<Button> event) {
String nickname = tfNickname.getValue();
String superType = lbSuperTypes.getValue();
List<String> powers = new ArrayList<>();
List<Component> componentList = cbLayout.getChildren().filter(child -> child instanceof Checkbox).collect(Collectors.toList());
List<Checkbox> cbPowers = componentList.stream().map(cb -> (Checkbox) cb).collect(Collectors.toList());
powers.addAll(cbPowers.stream().map(cbPower -> cbPower.getLabel()).collect(Collectors.toList()));
Super newSuper = new Super(nickname, SuperType.lookup(superType), powers);
System.out.println("Adding a new Super");
dataService.createSuper(newSuper);
}
Now, I fully expected Vaadin to throw runtime exceptions when I ran my app; I figured since DataService
is living on the server, and the ManagementView
is cross-compiled into client-side HTML/CSS/JS, that when the AddSuperClickListener
fired, that the whole thing would explode and throw an exception…
Instead, everything works PERFECTLY FINE!!! I can fill out the form underneath the Supers tab and press the “Add” button, and in the terminal, sure enough, I see the following console output:
Adding a new Super
New super added to the store!
How is this possible?!?! What is going on here that allows this to work? Is Vaadin somehow automagically creating an AJAX request between the browser and the server? I have so many questions!