Skip to main content Skip to footer

Two-way Bindings in Wijmo for Vue

Two-way binding looks like a quite contentious technology nowadays. Authors of all major modern frameworks urge you to use so-called one-way data flow, where the two-way binding concept doesn't fit well. The main idea behind that lies in that changes in the data model should update the corresponding UI controls (usually using one-way bindings), while the UI control whose value changes as a result of the user interaction with the control, should not perform hidden uncontrolled updates the model.

Meanwhile, at some moment of your application development, you come to the need to process user input and update the underlying data model with the values entered by the user. Such pieces of the application, often referred to as input forms, should offer a UI with input elements, which communicate with the underlying data model. Input control values are initialized with the model values, and then the new values entered by a user into the input controls should be somehow reflected in the model, for the farther processing of the new model data, for example for sending it to a server.

The standard approach to resolve this collision, where an input control should not perform hidden uncontrolled updates to the data model on the one hand, but such an update is needed, on the other hand, looks as follows:

  • Input control value property is one-way bound to the underlying model property. So updates to the model will be automatically reflected in the control.
  • Application code subscribes to an input control event which informs about the control value change (made by a user, particularly). And in the event handler, the JavaScript code updates the model property.

For example, as it made in this example from the Vue documentation, where HTML input control should update the searchText model property:

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

With this code, there is no hidden update of the model property made by the control. The update logic is clearly expressed in the event handler code.

But there is a share of guile in this implementation, because semantically this is just a two-way binding, barely implemented in a more verbose manner.

So why not write this code more concisely, something like this:

<input
  v-model="searchText"
>

This would make the code clearer, less error-prone, and most importantly, it would lead to smaller code size.

Some framework authors recognized this contradiction and introduced a special syntax to establish two-way data bindings. And Vue is not an exception. Behind the curtain, the framework expands such declaratively defined two-way bindings into the pair of the one-way binding plus the event handler that updates the model value, as was shown in the example above.

Vue Two-way Bindings

An input component may have plenty of different properties, but usually, only a few of them (and often just a single one) make sense in two-way bindings. This is a property that can change its value as a result of the user interaction with the control. This is the opposite to the case where control value can be solely changed by a JavaScript code of the application. For such a property whose value can be changed by a user, the control usually offers an event that notifies you about the property change. Without such an event, there is no simple way to know about the property change.

For example, Wijmo InputNumber control has the isReadOnly property, which is a bad candidate for the use in two-way bindings, because the only way to change its value is from JavaScript code. While the value property containing a control value is what you may want to use in two-way bindings, because it can be changed by a user. And there is a corresponding valueChanged event which is triggered when the value changes.

Vue provides two different ways to establish a two-way binding between an input component and the parent component's data model -v-model directive and sync modifier for the v-bind directive. Their functionality seems to be equal, but sync modifier provides a flexibility in choosing an input control property used as the binding target, in case where the input controls have more than one "value" properties. Wijmo input controls support both syntaxes.

Using v-model

When v-model is used, the control property participating in the binding is usually either a value property for the controls like InputNumber or InputDate, or selectedValue for the list-like controls like ListBox or ComboBox.

In the example below, the ComboBox control with the binding established by the v-model directive will update the ComboBox.selectedValue property:

<wj-combo-box
    :itemsSource="countries"
    v-model="theCountry">
</wj-combo-box>

Using .sync modifier

But ComboBox has two other properties that you may want to use in two-way bindings, selectedIndex and selectedItem. To bind to one of them, you have to use a syntax with the sync modifier, which allows you to explicitly define the control property to bind to.

This example binds a model property to the ComboBox.selectedIndex property:

<wj-combo-box
    :itemsSource="countries"
    :selectedIndex.sync="theCountryIndex">
</wj-combo-box>

Vue Two-way Bindings Conclusion

Two-way bindings is a powerful mechanism that simplifies the creation of the input forms. Vue offers two different syntaxes for declaring two-way bindings, the v-model directive, and the sync binding modifier. Wijmo for Vue input components support both of them, so you can choose between them depending on your preferences and specific needs.

You can find examples of Wijmo two-way bound controls in this live sample, where ComboBox and InputNumber are used in the cell edit templates.

Additional Reading:

Alex Ivanenko

Program Manager
comments powered by Disqus