Element Bindings
- Binding Rules
- Text Binding
- Attribute Binding
- Property Binding
- Flashing a CSS Class
- ClassList Binding
- Style Binding
- ThemeList Binding
- Visibility Binding
- Enabled Binding
- Change Callbacks
- HTML Content Binding
- Form Field Bindings
- SignalPropertySupport Helper
This section covers low-level Element bindings for direct DOM manipulation. These APIs are useful when building custom components or when you need fine-grained control over element attributes and properties.
|
Note
|
For most applications, use the component-level binding methods covered in Component Bindings. Component methods like
|
Binding Rules
All element bindings follow consistent rules:
-
When a feature is bound to a signal, its value is kept synchronized with the signal value while the element is in the attached state
-
When the element is detached, signal value changes have no effect
-
Passing
nullas the signal unbinds the existing binding -
While a signal is bound, any attempt to set the value manually (other than through the signal) throws
BindingActiveException -
Attempting to bind a new signal while one is already bound throws
BindingActiveException
Text Binding
Source code
Element#bindText(Signal<String> signal)
Element#bindText(Signal<String> signal)// SharedNumberSignal's Double type must be mapped to String
Signal<String> signal = counter.map(value -> String.format("Clicked %.0f times", value));
span.getElement().bindText(signal);
// span's text content is now "Clicked 0 times"Source code
Binding lifecycle
span.getElement().getText(); // returns "Clicked 0 times"
span.getElement().setText(""); // throws BindingActiveException
span.getElement().removeFromParent(); // detaching from the UI
span.getElement().getText(); // returns "Clicked 0 times"
span.getElement().setText(""); // throws BindingActiveException
counter.set(5); // updating the signal value
span.getElement().getText(); // returns "Clicked 0 times"
add(span); // re-attaching the element to the UI
span.getElement().getText(); // returns "Clicked 5 times"
span.getElement().bindText(null); // unbinds the existing binding
span.getElement().getText(); // returns "Clicked 5 times"
span.getElement().setText("");
span.getElement().getText(); // returns ""Attribute Binding
Source code
Element#bindAttribute(String attribute, Signal<String> signal)
Element#bindAttribute(String attribute, Signal<String> signal)ValueSignal<String> label = new ValueSignal<>("Close dialog");
button.getElement().bindAttribute("aria-label", label);
// DOM has "<button aria-label="Close dialog">"
label.set(null);
// DOM has "<button>" (attribute removed)Property Binding
Property binding supports various value types: String, Boolean, Double, BaseJsonNode, Object (bean), List and Map.
|
Note
|
Typed Lists and Maps are not supported. The signal must be of type Signal<List<?>> or Signal<Map<?,?>>.
|
Element#bindProperty(String name, Signal<T> signal, SerializableConsumer<T> writeCallback)The third parameter is a write callback that propagates client-side property changes back to the signal. Pass null for read-only bindings where changes only flow from signal to element.
Source code
Java
ValueSignal<Boolean> hidden = new ValueSignal<>(false);
span.getElement().bindProperty("hidden", hidden, null);
hidden.set(!hidden.peek()); // toggles 'hidden' propertySource code
String type
ValueSignal<String> title = new ValueSignal<>("Hello");
span.getElement().bindProperty("title", title, null);
title.set("World"); // updates 'title' propertySource code
Double type
SharedNumberSignal width = new SharedNumberSignal();
width.set(100.5);
span.getElement().bindProperty("width", width, null);
width.incrementBy(50); // updates 'width' property to 150.5Source code
Object (bean) type
record Person(String name, int age) {}
ValueSignal<Person> person = new ValueSignal<>(new Person("John", 30));
span.getElement().bindProperty("person", person, null);
person.set(new Person("Jane", 25));
// element.person is now {name: 'Jane', age: 25}Source code
List type
ValueSignal<List<String>> items = new ValueSignal<>(List.of("Item 1", "Item 2"));
span.getElement().bindProperty("items", items, null);
items.set(List.of("Item A", "Item B", "Item C"));
// element.items is now ['Item A', 'Item B', 'Item C']Source code
Map type
ValueSignal<Map<String, String>> config = new ValueSignal<>(Map.of("key1", "value1"));
span.getElement().bindProperty("config", config, null);
config.set(Map.of("key1", "value1", "key2", "value2"));
// element.config is now {key1: 'value1', key2: 'value2'}Source code
Two-way binding with property change listener
ValueSignal<Boolean> hidden = new ValueSignal<>(false);
// Bind the 'hidden' property to the signal with a write callback for two-way sync
span.getElement().bindProperty("hidden", hidden, hidden::set);
// Add a property change listener that synchronizes on 'change' DOM event
span.getElement().addPropertyChangeListener("hidden", "change", event -> {
// When the property changes on the client (via DOM event),
// the changed value is propagated back to the signal via the write callback
Notification.show("'hidden' property changed to: " + event.getValue());
});
// After a property change event from the client, signal.get() returns the updated valueFlashing a CSS Class
Element#flashClass(String className)Use flashClass() to temporarily add a CSS class that triggers a CSS animation, then automatically removes it when the animation ends. This is useful for visual feedback like highlighting a value that changed:
Source code
Java
element.flashClass("highlight");The method removes the class (if present), forces a DOM reflow, and re-adds it to restart the animation. An animationend listener removes the class when the animation completes. If no CSS animation is defined for the class, it is removed immediately.
Define the animation in CSS:
Source code
CSS
.highlight {
animation: flash 0.5s ease-out;
}
@keyframes flash {
from { background-color: yellow; }
to { background-color: transparent; }
}You can combine flashClass() with signal effects to flash whenever a value changes:
Source code
Java
SharedNumberSignal counter = new SharedNumberSignal();
Span counterSpan = new Span();
counterSpan.bindText(counter.map(c -> String.format("Count: %.0f", c)));
Signal.effect(counterSpan, () -> {
counter.get(); // Track the counter signal
counterSpan.getElement().flashClass("highlight");
});ClassList Binding
Source code
ClassList#bind(String name, Signal<Boolean> signal)
ClassList#bind(String name, Signal<Boolean> signal)ValueSignal<Boolean> foo = new ValueSignal<>(false);
ValueSignal<Boolean> bar = new ValueSignal<>(true);
span.getElement().getClassList().bind("foo", foo);
span.getElement().getClassList().bind("bar", bar);
// DOM has "<span class='bar'>"
foo.set(true);
// DOM has "<span class='bar foo'>"
span.getElement().getClassList().clear();
// DOM has "<span class>". Binding is also removed.Style Binding
Source code
Style#bind(String name, Signal<String> signal)
Style#bind(String name, Signal<String> signal)ValueSignal<String> color = new ValueSignal<>("black");
ValueSignal<String> background = new ValueSignal<>("white");
span.getElement().getStyle().bind("color", color);
span.getElement().getStyle().bind("background", background);
// DOM has "<span style='color: black; background: white'>"
color.set("red");
background.set("gray");
// DOM has "<span style='color: red; background: gray'>"
background.set(""); // same with null
// DOM has "<span style='color: red;'>"
span.getElement().getStyle().clear();
// DOM has "<span style>". Binding is also removed.ThemeList Binding
Source code
ThemeList#bind(String name, Signal<Boolean> signal)
ThemeList#bind(String name, Signal<Boolean> signal)ValueSignal<Boolean> darkMode = new ValueSignal<>(false);
component.getThemeList().bind("dark", darkMode);
// Theme "dark" is applied when darkMode is true
darkMode.set(true);
// Component now has "dark" theme appliedFor component-level theme binding examples, see Binding Theme Variants.
Visibility Binding
Components provide bindVisible() directly. The Element-level binding follows the same pattern:
Source code
Element#bindVisible(Signal<Boolean> signal)
Element#bindVisible(Signal<Boolean> signal)ValueSignal<Boolean> visible = new ValueSignal<>(true);
element.bindVisible(visible);
// Element is visible when visible is true
visible.set(false);
// Element is now hiddenFor component-level examples, see Binding Visibility.
Enabled Binding
Components provide bindEnabled() directly. The Element-level binding:
Source code
Element#bindEnabled(Signal<Boolean> signal)
Element#bindEnabled(Signal<Boolean> signal)ValueSignal<Boolean> enabled = new ValueSignal<>(true);
button.getElement().bindEnabled(enabled);
// Button is enabled when enabled is true
enabled.set(false);
// Button is now disabledFor component-level examples, see Binding Enabled State.
Change Callbacks
All binding methods return a SignalBinding that supports change callbacks via onChange():
Source code
Java
span.bindText(priceSignal.map(p -> "$" + p))
.onChange(ctx -> {
if (ctx.isBackgroundChange()) {
ctx.getElement().flashClass("highlight");
}
});The BindingContext provides:
-
getOldValue()/getNewValue()— the previous and current bound values -
getElement()— the target element -
getComponent()— the owning component (if any) -
isInitialRun()— whether this is the first execution -
isBackgroundChange()— whether triggered by another session or background thread
HTML Content Binding
Source code
Html#bindHtmlContent(Signal<String> signal)
Html#bindHtmlContent(Signal<String> signal)ValueSignal<String> htmlContent = new ValueSignal<>("<strong>Bold text</strong>");
Html html = new Html("<span></span>");
html.bindHtmlContent(htmlContent);
// HTML content is now "<strong>Bold text</strong>"
htmlContent.set("<em>Italic text</em>");
// HTML content is now "<em>Italic text</em>"|
Warning
| Be careful with HTML content binding to avoid XSS vulnerabilities. Never bind user-provided content directly without proper sanitization. |
Form Field Bindings
Form field bindings provide two-way synchronization between fields and signals. For comprehensive examples including all supported field types, see Two-Way Form Field Binding in Component Bindings.
Two-Way Value Binding
HasValue#bindValue(Signal<V> signal, SerializableConsumer<V> setter)The bindValue() method creates a two-way binding between a form field and a signal:
Source code
Java
ValueSignal<String> nameSignal = new ValueSignal<>("");
TextField nameField = new TextField("Name");
nameField.bindValue(nameSignal, nameSignal::set);
// User types in field -> signal is updated via setter
// Signal changes -> field is updatedRead-Only Binding
HasValue#bindReadOnly(Signal<Boolean> signal)Binds the read-only state of a form field to a boolean signal:
Source code
Java
ValueSignal<Boolean> readOnly = new ValueSignal<>(false);
TextField field = new TextField();
field.bindReadOnly(readOnly);
readOnly.set(true);
// Field is now read-onlyRequired Indicator Binding
HasValue#bindRequiredIndicatorVisible(Signal<Boolean> signal)Binds the required indicator visibility of a form field to a boolean signal:
Source code
Java
ValueSignal<Boolean> required = new ValueSignal<>(true);
TextField field = new TextField("Name");
field.bindRequiredIndicatorVisible(required);SignalPropertySupport Helper
Not all component features delegate directly to the state in Element. For those features, the SignalPropertySupport helper class ensures that state management behaves consistently with other element bindings.
Source code
Java
class MyComponent extends Div {
private final SignalPropertySupport<String> textProperty =
SignalPropertySupport.create(this, value -> {
getElement().executeJs("this.textContent = 'Content: ' + $0", value);
});
public String getTextContent() {
return textProperty.get();
}
public void setTextContent(String text) {
textProperty.set(text);
}
public void bindTextContent(Signal<String> textSignal) {
textProperty.bind(textSignal);
}
}Usage:
Source code
Java
MyComponent component = new MyComponent();
component.bindTextContent(counter.map(v -> "Signal value: " + v));
add(component);
// textContent in browser is "Content: Signal value: 0.0"
component.getTextContent(); // returns "Signal value: 0.0"
component.setTextContent(""); // throws BindingActiveException
component.bindTextContent(null); // unbinds the existing binding
component.setTextContent("");
component.getTextContent(); // returns ""