Handling Events
Flow passes user interaction back to the server side as component events. The application can handle these events in Java code using an event handler.
To handle user interaction, Vaadin Flow uses event-driven programming. A user’s interaction with the UI in the browser causes events. Flow passes the events from the browser to the server side, where your application code can handle them. You need to implement an event listener for each component that the user can interact with.
You can implement event listeners with regular classes, anonymous classes, lambda expressions, or method references.
Implementing an Event Handler
The traditional and verbose way to handle events is to implement an interface for the event type.
Each type of user interaction fires a different event type. For example, clicking a button fires a ClickEvent<Button>
event. Such events can be handled by implementing a ComponentEventListener
for the event type. The events are handled in the onComponentEvent()
method.
An event listener needs to be added to the component with an event-type-specific method add*Listener()
, such as addClickListener()
.
Many components also allow you to pass the listener in the constructor.
The following example shows how to implement a click listener as a local class:
new tab
Button button = new Button("Click me!");
class MyClickListener
implements ComponentEventListener<ClickEvent<Button>> {
int count = 0;
@Override
public void onComponentEvent(ClickEvent<Button> event) {
event.getSource()
.setText("You have clicked me " + (++count) + " times");
}
}
button.addClickListener(new MyClickListener());
add(button);
As shown in the example, you can access the originating component with getSource()
from the event.
Lambda Expressions
Lambda expressions are the easy way in Java to implement interfaces that only have a single method to implement, which is the case with event listeners.
For example, a lambda expression can be used to handle button click events, as follows:
new tab
Button button = new Button("Click me!",
event -> event.getSource().setText("Clicked!!!"));
add(button);
Most components, like Button above, allow you to pass a listener to the constructor.
For others, you need to use an add*Listener()
method, such as addClickListener()
, as in the other, earlier example.
Using Anonymous Classes
Anonymous classes are another shorthand way to implement handlers. They are more explicit than lambda expressions with the parameter type, and so can make the code clearer. They can also have a state, like normal classes.
The following example defines an anonymous class that inherits the Button.ClickListener
interface.
new tab
Button button = new Button("Click me!",
new ComponentEventListener<ClickEvent<Button>>() {
int count = 0;
@Override
public void onComponentEvent(ClickEvent<Button> event) {
event.getSource().setText("You have clicked the button "
+ (++count) + " times");
}
});
add(button);
Most components, such as Button, allow you to pass a listener to the constructor.
For others, you need to use an add*Listener()
method, such as addClickListener()
.
To be able to access the component from the anonymous listener class, you can have a reference to the component that’s declared before the constructor is executed. This could be, for example, as a member variable in the outer class. You can also get a reference to the component from the event object, as in the previous example.
Handler Methods
You can also direct events to methods with method references:
new tab
class ButtonBar extends HorizontalLayout {
public ButtonBar() {
add(new Button("OK", this::ok));
add(new Button("Cancel", this::cancel));
}
public void ok(ClickEvent<Button> event) {
event.getSource().setText("OKed!");
}
public void cancel(ClickEvent<Button> event) {
event.getSource().setText("Canceled!");
}
}
add(new ButtonBar());
CCE5013C-5167-4EF2-9542-70ACB0E8F885