How-To: Add Two-Way Binding to Blazor Page

In order to support taking user input in components and pages, Blazor supports a form of two-way binding which updates either when the user makes a change in the element or when the system updates the backing property/variable. When the variable changes, this two-way binding works exactly like one-way binding – the component is rendered with the new data. However, when the user changes an HTML input element (be that text or number or select, etc.), then that value gets updated in the bound variable.

For this article, we will first create a new Blazor page following the steps in the How-To: Create New Blazor Page article.

For two-way binding, we will use the @bind- directive. This directive is prepended onto an element attribute to specify which HTML attribute is being bound. For example: @bind-value = "@myVariable" two-way binds the HTML element’s value attribute to the myVariable member in the @code block.

Let’s create a binary to decimal converter page to show how two-way binding works:

@page "/page-2"

<h3>Binary-Decimal Converter</h3>
<form class="form-row col-lg-4 col-md-12">
    <div class="form-group col-12">
        <label for="binary">Binary:</label>
        <input type="text" class="form-control" id="binary"
               placeholder="Enter binary number" @bind-value="@binary">
    </div>
    <div class="form-group col-12">
        <input id="convert-decimal" type="button"
               value="Convert to Decimal" @onclick=ConvertToDecimal />
    </div>
    <div class="form-group col-12">
        <label>Decimal Result: @result</label>
    </div>
</form>

@code {
    string binary;
    string result;

    void ConvertToDecimal()
    {
        try
        {
            result = Convert.ToInt32(binary, 2).ToString();
        }
        catch
        {
            result = "Error: not a valid binary number.";
        }
    }
}

The page starts by specifying a route to this page mapped to ‘/page-2’.

Then, let’s look at the @code block:

  • We define two variables to hold our string representations (lines #20-21): binary (input variable) and result (post conversion value).
  • Then we define a ConvertToDecimal method (lines #23-33), which takes the value of binary and converts it to an integer value.
  • And, it places that converted value into the result variable.
  • Finally, if there are any errors in the conversion (like the user input is invalid), we set an error message in the result variable instead.

We define the two-way binding in lines #7-8. We two-way bind the value of the <input> element to the binary variable, using the following syntax:

        <input type="text" ... @bind-value="@binary">

Two-way binding in Blazor uses a naming convention to support the @bind- directive. If we want to bind to a property named MyProperty, then that component must have an event callback named MyPropertyChanged. That event callback must be called any time the component updates MyProperty. For the <input> element above, it has a value property and it has a valueChanged event callback, so we can use @bind-value to specify a two-way binding.

If we tried to two-way bind to a property that did not also have the required, matching event callback, we would get an InvalidOperationException when the page rendered. The exception would say that the component did not have a property matching the name MyPropertyChanged.

Also, if we were trying to two-way bind to a read-only property, we would also get an error when the page rendered about not being able to set the bound property. A read-only property does not have a public setter.

Finally, we use one-way binding to bind the button onclick event to call the ConvertToDecimal method (line #12), and the <label> to display the value for result (line #15). To review how one-way binding works, please read that article.

That’s the complete code for the binary-decimal converter. Let’s build the code and run our new page (Ctrl+F5). We will see that following page:

Fig 1 – Example of Two-Way Binding

We can test out various binary numbers to verify that the conversion works as expected. If it does work, we know that the two-way binding is working, because our conversion method uses the bound binary variable to perform the calculation, and doesn’t try to find the value from the HTML element.

While this article only shows two-way binding to an <input> element, it is possible to do with all of the different HTML input elements (select, number control, date picker, etc). And not only can we bind to values, it is possible to two-way bind to most attributes in HTML elements.

In conclusion, we learned how to specify a two-way binding to a page variable, but the concept works the same for binding to properties. We learned about the convention Blazor uses for defining property and event callback for a component to support two-way binding. And we saw how to use a two-way binding to capture text entered into an <input> element.

2 thoughts on “How-To: Add Two-Way Binding to Blazor Page

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s