Bidirectional binding enhancement
John Hendrikx
hjohn at xs4all.nl
Wed Nov 10 11:10:56 UTC 2021
Although I think you have a valid use case, I don't think JavaFX should
facilitate this exact scenario; it is a high level concern that you want
to solve in a very low level mechanism. A similar scenario also applies
to uni-directional bindings, so I think it would have to apply there as
well.
It also really depends on how you are doing the communication between
view and model. Some system use models that are always valid, some
systems use a view-model that contains a direct copy of what is in the
UI controls. Some views allow users to type anything and do validation
on submission or focus loss; some do per character validation and mark
bad input; some will not even allow you to type bad input.
For a scenario like you describe, which seems to be about delayed
updates of bindings, I think you really want to use something like
ReactFX's EventStreams. These offer far more features, including
timeouts, removal of duplicates, combining of values, conditional
suspending, etc. It might work like this for example:
EventStream.of(textInput.textProperty())
.conditionOn(textInput.focusedProperty().not())
.feedTo(model::valueProperty);
Or with Val:
Val.of(textInput.textProperty())
.conditionOn(textInput.focusedProperty().not())
.subcribe(v -> updateModel(v));
(Note: conditionOn is part of the fluent bindings proposal that Nir
Lisker and me have been working on).
Now, this isn't bidirectional, but I don't see how that will work in any
case as there are some edge cases. For example, how would you handle a
model update when the view is currently being edited? Delaying updates
runs into issues where both may have changed, whereas currently bindings
are resolved immediately on the FX thread.
--John
On 10/11/2021 06:45, Michael Strauß wrote:
> JavaFX developers routinely use programming patterns like MVC, MVP, or
> MVVM to separate views from their associated business logic. Bindings
> can be used to connect the values of UI controls (like Label or
> TextField) to properties on a business logic class.
>
> A typical (simplified) scenario may look like this:
>
> var valueField = new TextField();
> valueField.textProperty().bindBidirectional(businessLogic.valueProperty());
>
> The business logic class may perform data validation or other actions
> on the value that was entered in the TextField. However, in many
> cases, it is neither necessary nor desirable for the binding to update
> the business-layer property on every single change (i.e. every single
> character that was typed by a user). For example, if a business rule
> verifies that the data entered by a user is formatted in a specific
> way, it's usually not a great experience to yield a validation error
> before the user has finished typing. Instead, it's often better to
> wait until the user has significantly interacted with a UI control
> before running business logic.
>
> For this reason, I propose to add a new type of binding to the
> javafx.beans.binding.Bindings class:
>
> void bindBidirectional(Property<T> target, Property<T> source,
> UpdateSourceTrigger trigger)
>
> UpdateSourceTrigger is an enumeration that allows developers to
> specify the condition on which changes of the target property will
> update the source property. Its values are:
>
> DEFAULT: Updates the source property on every change (this is the
> default behavior of bidirectional bindings).
> FOCUS: Updates the source property when the UI control loses input focus.
> ACTION: Updates the source property when the UI control loses input
> focus or when it receives an ActionEvent (in the case of TextField,
> this corresponds to the ENTER key).
>
> Note that this setting only applies to changes of the target property.
> When the source property is changed instead, the target property is
> always immediately updated.
>
> Any feedback on this proposal is appreciated.
>
More information about the openjfx-dev
mailing list