-
Notifications
You must be signed in to change notification settings - Fork 181
Add helper for using signal effects with components #21629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
Comments
For reference, this is how I implemented this class in a prototype: public class ComponentEffect {
private final Runnable task;
private boolean closed = false;
private Runnable effectShutdown = null;
private ComponentEffect(Component owner, Runnable task) {
this.task = task;
owner.addAttachListener(attach -> {
enableEffect();
owner.addDetachListener(detach -> {
disableEffect();
detach.unregisterListener();
});
});
if (owner.isAttached()) {
enableEffect();
}
}
private void enableEffect() {
if (closed) {
return;
}
assert effectShutdown == null;
effectShutdown = Signal.effect(task);
}
private void disableEffect() {
if (effectShutdown != null) {
effectShutdown.run();
effectShutdown = null;
}
}
public void close() {
disableEffect();
closed = true;
}
public static Registration effect(Component owner, Runnable task) {
ComponentEffect effect = new ComponentEffect(owner, task);
return effect::close;
}
public static <C extends Component, T> Registration bind(C owner,
Signal<T> signal, BiConsumer<C, T> setter) {
return effect(owner, () -> {
setter.accept(owner, signal.value());
});
}
public static <C extends Component> Registration format(C owner,
BiConsumer<C, String> setter, String format, Signal<?>... signals) {
return effect(owner, () -> {
Object[] values = Stream.of(signals).map(Signal::value).toArray();
setter.accept(owner, String.format(format, values));
});
}
} |
mshabarov
added a commit
that referenced
this issue
Jun 16, 2025
vaadin-bot
pushed a commit
that referenced
this issue
Jun 16, 2025
vaadin-bot
added a commit
that referenced
this issue
Jun 16, 2025
Fixes #21629 Co-authored-by: Mikhail Shabarov <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Describe your motivation
When configuring a component instance using a signal, you want the signal effect to be deactivated when the target component is detached to avoid leaking memory. For convenience, the effect should be enabled again if the component is attached again. There's also an opportunity for a limited set of helper methods for common cases, e.g. when a single signal value is bound directly to a single component setter or for formatting a string based on one or several signals.
Describe the solution you'd like
Base functionality for creating a generic effect that is active while a target component is attached.
Bind a single signal to a setter on the component
Bind a formatted string based on 1..n signals.
All methods return a
Registation
that can be used to close the underlying effect and remove any attach/detach listeners.Describe alternatives you've considered
We might want to eventually integrate this kind of functionality directly in the base
Component
class but that makes sense only after the feature flag is removed.The ordering of arguments is inconsistent between the
bind
and theformat
overloads. This is on purpose:format
takes a list of signals as varargs which forces that to be last whereasbind
uses the regular "from, to" order of parameters. This ordering forbind
does also keep the door open for adding something likebind(component, signal, converter, setter)
in the future. In all cases, the component instance is an "implicit this" and does therefore always come first.The text was updated successfully, but these errors were encountered: