Introduction
This is chapter 11 in our journey to learn Blazor, Here is my publicly available repository with all source code available. BlazingBlazor.
Following are the chapters I've covered so far. Have a peek.
1. One way binding
The direction of one way goes from source to destination. Source being C# properties or variables and desination is HTML element.
How to use it? It's very straightforward. Just use @ in HTML and refer to C# properties or variables.
<label>Name:</label>
<input type="text" value=@UserName>
<br>
@code
{
public string UserName = "Martin Luther King Jr.";
}
Listing 1: one way binding
![One way binding in blazor]()
Image 1: Output of listing 1
2: Two way binding
It means flow could be from both directions from source to destination and from destination to source.
Scenario: To understand this we are going to use 2 input tags and we'll enter something in first input box which will get stored in c# property and then we'll bind same C# property to second input tag. In order to test 2 way binding mode we'll change text in second input tag which will eventually change text in first input-tag.
Two way data binding in razor components is accomplished with the @bind attribute.
@page "/"
<label>This is I am entering: </label>
<input type="text" @bind="@UserName">
<br>
<br>
<label>This is coming from top:</label>
<input type="text" @bind="@UserName">
@code
{
public string UserName { get; set; }
}
Listing 2: Two way binding
Now observe how these 2 input tags react with data when I lose focus from them.
![Two way binding in blazor]()
Gif 1: Output of listing 2
Let's take it up a notch. UI is updating when control leaves the focus. What if I want to update the input tag as soon as I enter something in another input tag?
In order to achieve this we have to make slight changes to code. With @bind attribute we need to define the triggering event which can be achieved with @bind-value:event attribute. This delegate will trigger the ValueChanged event of the component. In following listing I've made respective changes.
@page "/"
<label>This is I am entering: </label>
<input type="text" @bind="UserName" @bind:event="oninput">
<br>
<br>
<label>This is coming from top:</label>
<input type="text" @bind="UserName" @bind:event="oninput">
@code
{
public string UserName { get; set; }
}
Listing 3: Binding with event trigger
![Two way binding in blazor]()
Gif 2: Output of listing 3
Here is a fun tip for you.
You can also use
<input type="text" @bind-value="UserName" @bind-value:event="oninput">
Instead of
<input type="text" @bind="UserName" @bind:event="oninput">
There is no significant difference between using these two attributes.
Since we are talking about event let just start with third type of binding in blazor
3. Event Binding
Event binding is as simple as data binding. Instead of property or variable, we need to pass method that's all.
Let me create a simple page with a button and status. I'll expose 2 events, button-click and double-click, based on this event I am changing the status message.
<button @onclick="ButtonClicked" @ondblclick="ButtonDoubleClicked"> Clik me! </button>
<br />
<h3>@Status</h3>
@code
{
public string Status { get; set; } = "Button is not clicked yet!";
private void ButtonClicked()
{
Status = "Button clicked once..";
}
private void ButtonDoubleClicked()
{
Status = "Button clicked twice..";
}
}
Listing 4: event binding
![Event Binding in Blazor]()
Gif 3: Output of listing 4
Event binding with parameters
Let's pass a boolean parameter in the ButtonClicked event and a string parameter in the ButtonDoubleClicked event.
<button @onclick="()=> ButtonClicked(true)" @ondblclick='()=> ButtonDoubleClicked("Button clicked twice")'> Clik me! </button>
Note: while passing string with ondblclick event, I am using single quote because HTML gets parsing issue with string literals.
Here are the event handling methods, both are accepting their respective parameters.
private void ButtonClicked(bool isSingleClick)
{
Status = "Button clicked once.." + isSingleClick;
}
private void ButtonDoubleClicked(string status)
{
Status = status;
}
Let's see this in action
![Event Binding in Blazor]()
gif 4 : Output of event with parameters
4. Binding multiple options
Let's say we have a multi select option such as <select> tag in HTML. we can either bind data which will hold selection or we can bind events which will trigger the selection-event.
4.1 Data binding
In the following snippet, I am looping through a list of cities and printing every city under <select> and as you noticed on line number 4 I've an array of strings named SelectedCities that are bound.
<label>
Select cities:
<br />
<select @bind="SelectedCities" multiple>
@if (Cities.Any())
{
@foreach (var city in Cities)
{
<option> @city</option>
}
}
</select>
</label>
<br />
<br />
<span>
Selected Cities: @string.Join(", ", SelectedCities)
</span>
@code
{
public List<string> Cities { get; set; } = new List<string>() { "Los Angeles", "Mumbai", "Rio", "Tokyo", "Shanghai" };
public string[] SelectedCities { get; set; } = new string[] { "Mumbai" };
}
Listing 5: multiple data binding
In following gif you'd notice how I am able to store multi selection from <select> tag
![multiple data binding in blazor]()
Gif 5: Output of listing 5
4.2 Event binding
Instead of @bind you can directly use @onchange event, This event will provide ChangeEventArgs which consist of a selected array of cities.
@page "/"
<label>
Select cities:
<br />
<select @onchange="SelectedCitiesChanged" multiple>
@if (Cities.Any())
{
@foreach (var city in Cities)
{
<option> @city</option>
}
}
</select>
</label>
<br />
<br />
<span>
Selected Cities: @string.Join(", ", SelectedCities)
</span>
@code
{
public List<string> Cities { get; set; } = new List<string>() { "Los Angeles", "Mumbai", "Rio", "Tokyo", "Shanghai" };
public string[] SelectedCities { get; set; } = new string[] { "Mumbai" };
void SelectedCitiesChanged(ChangeEventArgs e)
{
if (e.Value is not null)
{
SelectedCities = (string[])e.Value;
}
}
}
Listing 6: multiple data with event binding
![multiple data with event binding]()
Gif 6: Output of listing 6
Bonus: @bind:format
<input @bind="dateNow" @bind:format="yyyy-MM-dd hh:mm:ss" />
private DateTime dateNow = DateTime.Now;
![@bind:format in blazor]()
Image 2: output of @bind:format
Conclusion
This is how you can achieve binding in Blazor, there are hundreds of options to bind various events, different types of data structures. Almost everything follows these basic concepts One-way binding, Two-way binding, Multi option binding, and event binding. I hope this article was helpful.