Q&A coffee break auf Deutsch am 12. April um 14 Uhr CEST

Ein kurze Zusammenfassung:

https://www.youtube.com/watch?v=3j1Q6od8F1c

Besprochene Themen

  1. [TwinColSelect API & Plattform Support]
    (https://vaadin.com/forum/thread/17608958/17608990)
  2. [Panel Komponente für Vaadin Plattform]
    (https://vaadin.com/forum/thread/17608958/17609005)
  3. [Kompatibilität zwischen Spring Boot und Vaadin Versionen]
    (https://vaadin.com/forum/thread/17608958/17609022)
  4. [Auflösung von Bildern in Abhängigkeit von Pixeldichte, Fenstergröße usw.]
    (https://vaadin.com/forum/thread/17608958/17609039)
  5. [Feature-Parität zwischen Vaadin 8 und Plattform]
    (https://vaadin.com/forum/thread/17608958/17609040)
  6. [CustomField und Binder]
    (https://vaadin.com/forum/thread/17608958/17609081)
  7. [AppLayout Komponente für klassische Header/Footer/Sidebar/Content UI]
    (https://vaadin.com/forum/thread/17608958/17609138)
  8. [Vaadin Roadmap und Features für Vaadin 14]
    (https://vaadin.com/forum/thread/17608958/17609174)
  9. [Verschiedene Optionen für responsive Design]
    (https://vaadin.com/forum/thread/17608958/17609280)

1. TwinColSelect API & Plattform Support

Diese Komponente gibt es leider noch nicht in Vaadin Plattform.

Wir haben eine Seite erstellt, auf der ihr sehen könnt, welche Komponenten bisher in Vaadin 10+ implementiert wurden bzw. wie sie überführt wurden. Diese Seite findet ihr in der Doku hier https://vaadin.com/docs/v13/flow/migration/5-components.html.

2. Panel Komponente für Vaadin Plattform

Vaadin Plattform hat [?noch?]
kein Panel. Du könntest es aber über folgenden CSS Style ändern:
component.getElement().getStyle().set(“overflow”, “auto”) und so das Tag scrollable machen.

3. Kompatibilität zwischen Spring Boot und Vaadin Versionen

Vaadin 7-8 wird durch Spring Boot 1.5.* und Vaadin Plattform durch Spring Boot 2.* unterstützt. Vaadin Plattform ist nicht kompatibel zu der Spring Boot Version 1.5*.

Für die Vaadin-Spring-Boot-Starter Dependency sieht man ganz gut im mvnrepository die Abhängigkeiten zur entsprechenden Vaadin Version oder im Vaadin Bom Projekt in der pom.xml. Hier kannst du die Vaadin Version entsprechend auswählen und dann nach der Property für die Spring Version schauen. Hier ist der Link: https://github.com/vaadin/framework/tree/master/bom

4. Auflösung von Bildern in Abhängigkeit von Pixeldichte, Fenstergröße usw.

Es gibt ein paar verschieden Möglichkeiten hier:

  1. Bei Grafiken wo es Sinn macht, sollte man in Betracht ziehen auf Vektorgrafiken in Form von SVGs oder Icon-Fonts zu setzen und so das Problem mit der Auflösung komplett zu umgehen. Das betrifft natürlich zumeist Icons, Logos u.ä.
  2. Häufig zu sehen aber nicht unbedingt die eleganteste Lösung, kann man das Thema auch über CSS Media Queries angehen. Das Hauptproblem dabei ist, dass man dabei keinen verlässlichen Zugriff auf das src Attribut des <img> Tags hat, d.h. letztendlich mit <div> Element und background-image arbeitet oder :before/:after Selektoren. In der gleichen Kategorie, jedoch auf der Java Server-Seite, wäre da der ResizeListener (siehe auch Punkt 9 weiter unten), der entsprechend die Bild-Quelle setzt.
  3. Die elegantere Variante ist die Verwendung des srcset Attributes des <img> Tags oder der <picture> Tag um mehrere Versionen einer Graifk und Kriterien für deren Verwendung zu definieren. Die erste Variante ist etwas weniger verbos, überlässt die finale Entscheidung aber dem Browser, die zweite gibt mehr Kontrolle über die Konditionen.

Hier ein paar kurze Beispiele:

HTML

<img src="https://dummyimage.com/128x128" srcset="https://dummyimage.com/128x128 1x, https://dummyimage.com/256x256 2x" width="128">
<img src="https://dummyimage.com/128x128" srcset="https://dummyimage.com/128x128 640w, https://dummyimage.com/256x256 800w" width="128">
<picture>
	<source media="(min-width: 800px)" srcset="https://dummyimage.com/512x512">
	<source srcset="https://dummyimage.com/128x128 1x, https://dummyimage.com/256x256 2x">
	<img src="https://dummyimage.com/128x128" alt="">
</picture>

Java (Vaadin Platform)

@Tag("picture")
public class Picture extends Component implements HasComponents {
}
@Tag("source")
public class Source extends Component {
}
public class MainViewImagesJavaOnly extends VerticalLayout {

	public MainViewImagesJavaOnly() {
		Image img = new Image("https://dummyimage.com/128x128", "");
		img.getElement().setAttribute("srcset",
				"https://dummyimage.com/128x128 640w, https://dummyimage.com/256x256 800w");
		add(img);

		Picture pic = new Picture();

		Source src = new Source();
		src.getElement().setAttribute("srcset", "https://dummyimage.com/512x512");
		src.getElement().setAttribute("media", "(min-width: 800px)");
		pic.add(src);

		Image img2 = new Image("https://dummyimage.com/128x128", "");
		img.getElement().setAttribute("srcset",
				"https://dummyimage.com/128x128 640w, https://dummyimage.com/256x256 800w");
		pic.add(img2);

		add(pic);
	}
}

Obiges Beispiel ist natürlich sehr minimalistisch. Es sei dem Leser als Fleißaufgabe selsbt überlassen, die Source und Image Klassen mit einer etwas eleganteren API auszustatten und so die getElement().setAtrtibute(...) Aufrufe weg zu abstrahieren.

5. Feature-Parität zwischen Vaadin 8 und Plattform

Wie Jürgen in der Coffee Break erwähnt hat, haben wir Vaadin Plattform schnell released um frühzeitig Feedback vom Markt zu bekommen und es basierend darauf weiter aufzubauen. Auf der folgenden Seite siehst du, welche Komponenten implementiert sind, welche noch folgen, oder welche Alternativen in Frage kommen.

https://vaadin.com/docs/v13/flow/migration/5-components.html

Siehe zu diesem Thema auch [Punkt 8 “Vaadin Roadmap und Features für Vaadin 14”]
(https://vaadin.com/forum/thread/17608958/17609174) weiter unten.

6. CustomField und Binder

Es wurde gefragt, ob man eine eigene Komponente die auf Grundlage von CustomField/AbstractCompositeField erstellt wurde, mit einem Binder verbinden kann und somit das DataBinding zu realiseren.

Ich sehe hier zwei Möglichkeiten:

  1. Die Komponente reicht die Felder via getter nach aussen und der Binder kann sie direkt integieren. Der Vorteil wäre, dass die Felder direkt mit Validatoren und Converter konfiguriert werden können allerdings ist die Implementierung etwas unelegant.

  2. Die CustomComponent kann das HasValue Interface implementieren und so in der getValue und setValue Methode die Werte zwischen der entsprechende Bean und den UI Komponenten überführen. Die Komponente kann dann einfach in den Binder integiert werden und die Validierung muss dann in den GetValue und SetValue Methoden oder durch die withValidationStatusHandler Methode am Binder erfolgen.

    Bei den Fehlermeldungen muss man darauf achten, dass sofern es nicht anders konfiguert wird, die Fehlermeldung direkt an der CustomComponent erfolgt und nicht an den einzelnen Elementen in der CustomComponent. Das müsste man wieder individuel konfiguriert werden.

7. AppLayout Komponente für klassische Header/Footer/Sidebar/Content UI

Es gibt bereits eine [AppLayout Komponente]
(https://vaadin.com/components/vaadin-app-layout/) seit Vaadin 12, wobei diese in der dort enthaltenen und derzeit aktuellen Version eine etwas andere Struktur hat (Action Bar oben oder unten und zentrale Content Area).

Die Unterstützung für das typische Layout aus Sidebar mit Hamburger-Icon und Content Area ist aber schon in Arbeit. Release Notes für die Alpha-Version sind [hier]
(http://https://github.com/vaadin/vaadin-app-layout/releases) und eine Demo gibt es [hier]
(https://cdn.vaadin.com/vaadin-app-layout/2.0.0-alpha2/demo/#element-basic-demos).

Vorgesehen ist das Ganze momentan für das Vaadin 14 Release (siehe [Roadmap]
(https://github.com/orgs/vaadin/projects/1)).

8. Vaadin Roadmap und Features für Vaadin 14

Generell lohnt sich der Blick auf die [Roadmap-Seite]
(https://vaadin.com/roadmap) auf vaadin.com. Dort verlinkt ist auch ein [Project-Board]
(https://github.com/orgs/vaadin/projects/1), das für die nächsten drei Versionen die Liste der geplanten Themen, sowie Release der Beta- und finalen Version nennt.

Die Version 14 hat sich das Ziel gesetzt eine möglichst gute Feature-Parität mit Vaadin 8, der letzten Version vor Vaadin Platform, zu erreichen. Dementsprechend finden sich auf der Task-Liste Themen wie

  • Drag & Drop Support
  • das Einbetten von Vaadin Anwendungen in Webseiten
  • eine MenuBar Komponente
  • mehr Notification Optionen
  • Grid Verbesserungen

sowie ein paar Themen unter der Haube, wie z.B. der Wechsel auf Polymer 3, npm und ES6 statt Polymer 2, Bower, WebJars und HTML Imports.

Das Release ist für den 5. Juni 2019 geplant.

Um das Ganze auch nochmal etwas in Kontext zu setzen: Vaadin Platform hatte bisher ein LTS Release, nämlich Version 10. Hier war das Ziel, die neuen Konzepte möglichst früh auf den Markt zu bringen und Erfahrung in der Breite zu sammeln. Ohne hier Qualität zu opfern, bedeutete dies natürlich sich bei den Features auf das absolut notwendinge zu konzentrieren. Mit Vaadin 11 bis 13 (nicht LTS) wurde bereits hart daran gearbeitet fehlende Features nachzuliefern, aber das finale Ziel hier ist natürlich Vaadin 14, das als LTS eine möglichst gute Parität zum Plattform Vorgänge Vaadin 8 schaffen soll. Für diejenigen, die sich bis jetzt mit der Migration zurecht etwas zurückgehalten hatten, dürfte Vaadin 14 der richtige Zeitpunkt sein, das Thema neu aufzurollen.

Trotzdem bitte daran denken, dass obige Pläne und Features nicht 100% fix sind und sich ändern können. Es kann immer passieren, dass ein Feature kurz vor Schluss Probleme macht und es am Ende doch nicht in das Release schafft.

9. Verschiedene Optionen für responsives Verhalten

Es kam die Frage auf, ob Responsive Design auch ohne die kommerzielle [Vaadin Board]
(https://vaadin.com/components/vaadin-board) Komponente möglich ist, und im Nachsatz, ob dann zwingend CSS erfolderlich sei.

Vaadin Board ist dazu gedacht, eine Reihe von häufigen Anwendungsfällen möglichst einfach abzudecken, ist aber absolut keine Voraussetzung für Responsive Design. Die Standard-Lösungen dafür, Vaadin oder nicht, sind typischerweise

  1. CSS Media Queries und/oder flexbox Layouts
  2. ein Listener für das window resize Event und entsprechende Logik um Elemente zu positionieren, Größen zu ändern etc.

Die erste Option ist dabei die üblichere und wohl in den meisten Fällen auch performantere Lösung. Während die zweite Option eher in Randfällen zum Einsatz kommt, wo man mit der ersten Variante nicht ans Ziel kommt (z.B. Grid-Spalten anzeigen oder nicht in Abhängigkeit von der Fenstergröße).

Option 1 funktioniert mit Vaadin Platform auf genau die gleiche Weise wie in einer einfachen HTML Seite und mit den meisten anderen Frameworks auch.

Option 2 lässt sich mit Vaadin Plattform ebenfalls relativ leicht umsetzen, auch wenn das nur in den wenigsten Fällen meine bevorzugte Option wäre. Wer mit HTML Templates arbeitet kann dort ganz einfach mit Javascript einen Event Listener registrieren, alternativ geht das aber auch auf der Server-Seite in Java:

@Route("")
public class MainViewSizing extends VerticalLayout {

	public MainViewSizing() {
		add(new Label("Test"));

		// Just for demo purposes
		getElement().setAttribute("style", "background-color: green;");
	}

	@Override
	protected void onAttach(AttachEvent attachEvent) {
		super.onAttach(attachEvent);

		Page page = getUI().get().getPage();
		page.addBrowserWindowResizeListener(e -> {
			if (e.getWidth() < 640)
				setWidth("100%");
			else
				setWidth("380px");
		});
	}
}

Hier noch ein kleiner Zusatz zur Frage Nr. 6

Wie schon gesagt, man kann die Felder die Bean Daten über Getter Methoden an einen externen Binder oder direkt in dem CustomField über einen “Nested” Binder anbinden. Beide Wege haben ihre Vor- und Nachteile. Ein interner Binder muss natürlich nur einmal definiert werden und spart entsprechend Code bei der Wiederverwendung. Wenn die Felder mit einem externen Binder verknüpft werden, ist man entsprechend flexibel bei der Konfiguration der Validatoren und Converter.

Also erweiterbare Komponenten kann man in Vaadin 8 auf das HasValue<BEAN> zurückgreifen.

public class AddressField extends CustomComponent implements HasValue<Address> {
	...
}

Mit der Vaadin Plattform muss man das HasValueAndElement<AddressComponent, Address> implementieren oder das AbstractCompositeField<VerticalLayout, AddressField, Address> erweitern.

Ich persönlich empfehle immer ein CustomField + HasValue Interface (V8) oder das AbstractCompositeField (V10+) zu verwenden, um das SoC (Seperation of Concern) sicherzustellen und eine nachträglich umgestaltung zu verhindern.