Blazor Events and Data Bindings

Blazor Events and Data Bindings

Blazor Event Handling is the process to respond to events like button click, select change, text change on text box, clipboard events, mouse events, etc. Then perfoming some work if the events happen. In the below example, there is a button having an onclick event. When this event happens, we are going to shoot an email.

<button @onclick="SendMail">
    Send Email
</button> 

@code {
    private void SendMail()
    {
        ...
    }
}
On my previous tutorial I created First Application in Blazor from scratch, if you haven’t gone through it make sure you do it now. It covers every type of file and their workings in Blazor.
<button @onclick="SendMail">
    Send Email
</button>

So, when this button is clicked then it calls the SendMail C# function. Inside this function you can write an email sending code.

Defining Events in Blazor

Any HTML element like button, select, input, etc can be added with an event by adding an attribute to it. This attribute name is @on followed by the event name. In the button case it was @onclick, which is for the click event for the button.

The value assigned to this attribute is the method called as Handler Method. This method is invoked when the event is triggered. In the button case – @onclick="SendMail", “SendMail” was the handler method.

The EventArgs Classes

Additional information about the event can be provided to the Handler Method by using the EventArgs class. For example, see the below updated code of the button click.

<button @onclick="SendMail">
    Send Email
</button> 

@code {
    private void SendMail(MouseEventArgs e)
    {
        ...
    }
}

The handler method now has a parameter of MouseEventArgs class which is inherited from the EventArgs class, and contains information about the mouse event that is raised. That is, I can get many informations like:

  • X and Y coordinates of the mouse pointer when the click event happened.
  • The button number that was pressed when the mouse event fired. Left button=0, middle button=1, right button=2.
  • Whether the CTRL, SHIFT, ALT key were down when the event fired.

In fact, their are lots of information which you can get. In the below table I have given the EventArgs classes and the Events they Represent.

Class Events
ChangeEventArgs onchange, oninput
KeyboardEventArgs onkeydown, onkeypress, onkeyup
ProgressEventArgs onabort, onload, onloadend, onloadstart, onprogress, ontimeout
ClipboardEventArgs oncopy, oncut, onpaste
MouseEventArgs onclick, oncontextmenu, ondblclick, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup, onmousewheel, onwheel

Behind the screen, this works in this way. The Blazor JavaScript code receives the event that is triggered and forwards it to the server over the persistent HTTP connection (SignalR). Then the handler method is invoked (on the server), and the state of the component is updated (on the server).

Next, the server sends back the changes on the page content to the JavaScript code, and this JavaScript code updates the content displayed on the browser. All this works instantly and without any page reload.

Common Blazor Events for HTML tags

One of the most popular event is the Blazor OnChange Event which is fired when the control value is changed. I will show some examples of how you can use the onchange event on HTML tags like buttons, input tags, select tags, checkbox and radio buttons and create your custom codes in the manner you want.

Example: Input type text “onchange” event

Create a new razor component called Iexample.razor inside the Pages folder of your project. Next, add the following code to it.

@page "/Iexample"

<h3 class="bg-secondary text-white">@MyName</h3>

<div class="form-group">
    <label>Name:</label>
    <input type="text" class="form-control" @onchange="Name"/>
</div>

@code {
    public string MyName { get; set; }

    private void Name(ChangeEventArgs e)
    {
        MyName = e.Value as string;
    }
}

The above code has an input type text tag which has an onchange event of Blazor. It calls a handler method called Name.

The blazor events are added with “@” sign like @onchange="Name". If we don’t put “@” then this becomes JavaScript events. This is something you should take a note.

When the user types anything on the text box (input type text) and then changes the focus. In this case the Blazor onchange event is fired and the MyName property value is set to the value of the text box.

The ChangeEventArgs parameter supplies information about the event to the hander. You can see I have grabbed the value of the text box as e.Value as string, and set the MyName property to this value.

MyName = e.Value as string;

The value of the MyName property is shown inside a “h3” tag:

<h3 class="bg-secondary text-white">@MyName</h3>

In the below video I have shown how it will work:

blazor onchange event textbox

Single Handler for Events from Multiple Elements

To avoid code duplication, you can use a Single Hander method for receiving events from multiple elements. See the below code that has 2 text boxes, one for receiving first name of the person and other for last name. There is only one hander method for 2 Blazor OnChange Event of text boxes.

@page "/Iexample"

<h3 class="bg-secondary text-white">@FullNameValue</h3>

<div class="form-group">
    <label>Full Name:</label>
    <input type="text" class="form-control" @onchange="@(e => FullName(e, null))" />
    <input type="text" class="form-control" @onchange="@(e => FullName(null, e))" />
</div>

@code {
    public string FullNameValue { get; set; }

    private void FullName(ChangeEventArgs e1, ChangeEventArgs e2)
    {
        if (e1 is not null)
            FullNameValue = e1.Value as string;
        if (e2 is not null)
            FullNameValue = FullNameValue + " " + e2.Value as string;
    }
}

Here I have used Lambda function of C# to invoke the FullName hander for the onchange events, and passing to them 2 parameters – ChangeEventArgs & Null in interchanging manner.

@onchange="@(e => FullName(e, null))"
@onchange="@(e => FullName(null, e))"

Then in the hander method I used the if condition to fetch out the first and last names from the 2 text boxes.

If you run the above code, it will work as show below:

Blazor OnChange Event from Multiple Elements

If you don’t need to use the EventArgs object, then you can omit the parameter from the lambda function, like shown below:

<input type="text" class="form-control" @onchange="@(() => ShowMessage("Hello"))" />
Events without Hander method

You can also process events without using hander method, this is done by using Lambda function. See the below code which shows a hello message on the button’s click event. The button onclick event has lambda function which does the event handling without a hander method.

<h3 class="bg-secondary text-white">@Message</h3>

<div class="form-group">
    <label>Message:</label>
    <button class="form-control" @onclick="@(() => Message="Hello")">Show Message</button>
</div>

@code {
    private string Message { get; set; }
}

Example: Select “onchange” event

The Blazor OnChange event works well with the HTML Select tag to. Now place select tag with “onchange” event as – @onchange="Option". See the below code:

@page "/Iexample"
<h3 class="bg-secondary text-white">@MyOption</h3>

<div class="form-group">
    <label>Name:</label>
    <select class="form-control" @onchange="Option">
        <option>Ram</option>
        <option>Jack</option>
        <option>Joe</option>
    </select>
</div>

@code {
    public string MyOption { get; set; }

    private void Option(ChangeEventArgs e)
    {
        MyOption = e.Value as string;
    } 
}

So, whenever an option is selected, then the handler method Option is called. This handler method gets the selected value through the ChangeEventArgs type parameter. It updates the MyOption property value to the selected value, and then the MyOption property value is shown inside an h3 tag.

See the below video which shows it’s working.

Blazor OnChange Event on HTML Select

Example: Checkbox “onchange” event

The onchange event can also be applied to checkbox. The only thing to note here is that the checkbox’s value is of type bool so you need to caste it on the hander method. See the below code:

@page "/Iexample"

<h3 class="bg-secondary text-white">@AgreeValue</h3>

<div class="form-group">
    <label>Agree to terms:</label>
    <input type="checkbox" @onchange="Agree" />
</div>

@code {
    public bool AgreeValue { get; set; }

    private void Agree(ChangeEventArgs e)
    {
        AgreeValue = Convert.ToBoolean(e.Value);
    }
}

It works as shown by the given video:

p>blazor onchange checkbox

Example: Radio Button “onchange” event

Radio buttons can be used with Blazor onchange event to find out the user’s selection. Note that here only 1 selection out of multiple options can be made. The below code illustrates this thing. Note that the name of the radio buttons should be made same (here I have given them the same name “sex”).

@page "/Iexample"
<h3 class="bg-secondary text-white">@SexValue</h3>

<div class="form-group">
    <label>Select sex:</label>
    <input type="radio" name="sex" value="Male" @onchange="YourSex" />Male
    <input type="radio" name="sex" value="Female" @onchange="YourSex" />Female
</div>

@code {
    public string SexValue { get; set; }

    private void YourSex(ChangeEventArgs e)
    {
        SexValue = e.Value as string;
    }
}

The working is shown by the below video:

blazor onchange radio button

Preventing Default Events (preventDefault) & Event Propagation (stopPropagation)

Suppose a button is kept inside an HTML form tag. Then on clicking the button, the form gets submitted. This is called as the default behaviour of a button click event.

Now suppose we add an onclick event to the button. Inside this event we do some work like increasing the counter by 1 every time the button is clicked. The code for this is given below.

@page "/Iexample5"
<h3 class="bg-secondary text-white">@Counter</h3>
<form>
    <div class="form-group">
        <label>Counter:</label>
        <button class="form-control" @onclick="IncreaseCounter">Increase Counter</button>
    </div>
</form>

@code {
    private int Counter { get; set; }

    private void IncreaseCounter(MouseEventArgs e)
    {
        Counter++;
    }
}

When you run this code you will notice that on clicking the button, the form gets submitted but the button’s onclick event will not be executed.

On clicking the button, the counter will not be increased, because the default behaviour of the buttons causes the problem and submits the form instead. This is shown by the below video:

Blazor Event Propagation

“preventDefault” Parameter

The solution of this problem is by adding the preventDefault parameter with the onclick event and set it’s value to “true”. The preventDefault parameter specifies whether to cancel the default action that belongs to the onclick event and takes a bool value. So update the code by adding one more onclick event with preventDefault parameter to the button – @onclick:preventDefault="true".

The updated code is shown in highlighted manner.

@page "/Iexample6"
<h3 class="bg-secondary text-white">@Counter</h3>
<form action="/Jexample" method="get">
    <div class="form-group">
        <label>Counter:</label>
        <button class="form-control" @onclick="IncreaseCounter" @onclick:preventDefault="true">Increase Counter</button>
    </div>
</form>

@code {
    private int Counter { get; set; }

    private void IncreaseCounter(MouseEventArgs e)
    {
        Counter++;
    }
}

This will solve the problem and now the button click will start increasing the counter value. See the below video:

Blazor preventDefault

Now let us see another problem arising due to Event propagation. Suppose I have a div tag that contains a button. Both the div and button have onclick events. So, when I click the button then both the onclick events get’s executed. That is, first the onclick event of the button is executed and then the onclick event of the div gets executed. This is an unexpected behaviour and happens due to propagation of events from child towards the parents.

I have created this problem in the below code:

@page "/Iexample7"
<h3 class="bg-secondary text-white">@Message1</h3>
<h3 class="bg-secondary text-white">@Message2</h3>
<div class="form-group" @onclick="@(() => Message1="Hello Google")">
    Show Message:
    <button class="form-control" @onclick="@(() => Message2="Hello Microsoft")">Show Message</button>
</div>

@code {
    private string Message1 { get; set; }
    private string Message2 { get; set; }
}

There are 2 properties called “Message1” & “Message2”. The div’s onclick event updates the “Message1” property to Hello Google while the onclick event of the button updates the “Message2” property to Hello Microsoft. Now when you click the button then you will receive both Hello Google & Hello Microsoft messages. This is because the div’s onclick event also gets called as the button is the child of this div.

I have shown this in the below video:

Blazor prevent Event Propagation

Note that event propagation happens from child till to root element of the DOM tree. So if we have more elements in the hierarchy then their events are also called.
“stopPropagation” Parameter

The solution of this problem is by using stopPropagation parameter with the onclick event and set it to “true”. The stopPropagation parameter specifies whether to stop the event propagation of the onclick event, and you need to set it to true.

So add one more onclick event to the button tag and set stopPropagation to true – @onclick:stopPropagation="true". The updated code is shown highlighted:

@page "/Iexample8"
<h3 class="bg-secondary text-white">@Message1</h3>
<h3 class="bg-secondary text-white">@Message2</h3>
<div class="form-group" @onclick="@(() => Message1="Hello Google")">
    Show Message:
    <button class="form-control" @onclick="@(() => Message2="Hello Microsoft")" @onclick:stopPropagation="true">Show Message</button>
</div>

@code {
    private string Message1 { get; set; }
    private string Message2 { get; set; }
}

Now run the code and see it works perfectly. See the below video:

Blazor Data Bindings

We can bind html controls with C# value using Blazor Data Binding. We are going to understand One Way Binding and Two Way Binding in Blazor. This concept is very frequently used so make sure you understand it correctly.

One Way Binding in Blazor

We can simply bind the value attribute of the HTML controls/tags with the C# property and this will show the C# property’s value inside the control. For example, in the below code we are binding an input type text tag to a C# property called Name.

<input class="form-control" value="@Name" />

@code {
    public string Name { get; set; } = "Blazor";
}

In the same way, we can use the value attribute in other html controls like select tag, radio button, etc. To understand it, lets take an example of the select control.

In the below given code, there is a select tag with 3 options for 3 coding frameworks. Note, it’s value attribute is bind to the Frameworks property. This property is defined in the code block.

There is a div tag which is given below the select control, and it shows the user selected “Frameworks” property’s value. This code is given below.

@page "/Binding1"
<div class="form-group">
    <label>Frameworks:</label>
    <select class="form-control" value="@Frameworks">
        <option value="Select">Select</option>
        <option>Blazor</option>
        <option>ASP.NET Core</option>
        <option>React</option>
    </select>
</div>

<div class="p-2 mb-2">Framework’s Value: @Frameworks</div>

@code {
    private string Frameworks { get; set; } = "ASP.NET Core";
}

Now run the code and you will notice that the select control is bind with the “ASP.NET Core” value from the very start and the div will be showing the Framework’s value which is “ASP.NET Core”.

Now change the select value to Blazor, and you will notice that the div value does not change i.e. it remains same as ASP.NET core.

See the below video which shows these things.

blazor one way data binding

The explanation of this thing is that here I have created only One Way Binding in Blazor. This means:

  • 1. Select control only got bind with the property value at the start.
  • 2. Select control is not able to change the value of this C# property.

Two Way Binding in Blazor

Now I will update the code to create Two Way Binding in Blazor. I will only add onchange event to the select control and it’s hander method will update the C# property to the value of the selected option of the select control. The updated code is shown highlighted:

@page "/Binding2"
<div class="form-group">
    <label>Frameworks:</label>
    <select class="form-control" value="@Frameworks" @onchange="UpdateFramework">
        <option value="Select">Select</option>
        <option>Blazor</option>
        <option>ASP.NET Core</option>
        <option>React</option>
    </select>
</div>
<div class="p-2 mb-2">Framework's Value: @Frameworks</div>

@code {
    private string Frameworks { get; set; } = "ASP.NET Core";
    private void UpdateFramework(ChangeEventArgs e)
    {
        Frameworks = e.Value as string;
    }
}

Notice I added @onchange="UpdateFramework" to the select control and the hander method UpdateFramework inside the code block. Now run your app in the browser and notice the change in the selected option of the select control will automatically update the value of the Frameworks property, and so the div now shows the updated value (which was not the case previously). This is Two Way Binding in Blazor.

See the below video which explains this scenario.

Blazor two way binding

Blazor “@bind” attribute

The @bind attribute can be applied to an html control and it directly provides Two Way Binding for the control. The @bind attribute specifies the property that will be updated when the change event of the control is triggered and that will also update the value attribute of the control.

So now you do not need a handler method or a lambda function to update the property.

We now make changes in the above code. Remove the value attribute and the onchange event from the select control and instead place @bind attribute and assign it to the Frameworks property – @bind="Frameworks". Also comment out or remove the hander method as it is not needed anymore. Check the given code below:

@page "/Binding3"
<div class="form-group">
    <label>Frameworks:</label>
    <select class="form-control" @bind="Frameworks">
        <option value="Select">Select</option>
        <option>Blazor</option>
        <option>ASP.NET Core</option>
        <option>React</option>
    </select>
</div>
<div class="p-2 mb-2">Framework's Value: @Frameworks</div>

@code {
    private string Frameworks { get; set; } = "ASP.NET Core";
    //private void UpdateFramework(ChangeEventArgs e)
    //{
    //    Frameworks = e.Value as string;
    //}
}

Run and see it works perfectly.

bind attribute Blazor

@bind and @onchange cannot be used together

Blazor prevents using @bind and @onchange attributes together. Now Suppose you come up with a situation where there is @bind attribute on a select element and you also need to do some other task on the onchange event. The work around for this is to call a property with @onbind attribute and on the property set code To do your task. See the below code which shows this thing.

@page "/Binding4"

<select class="form-control" @bind="ChangeFramework">
	<option value="Select">Select</option>
	<option>Blazor</option>
	<option>ASP.NET Core</option>
	<option>React</option>
	<option>Help</option>
</select>
<div class="p-2 mb-2">Framework's Value: @Frameworks</div>

@code {
	private string Frameworks { get; set; } = "ASP.NET Core";
	public string ChangeFramework
	{
		get { return Frameworks; }
		set
		{
			Frameworks = value;
			if (Frameworks == "Help")
			{
				// call ambulance
			}
		}
	}
}

This approach will come handy in certain areas.

Changing the Default Binding Event – “@bind-event”

By default, the onchange event is used in bindings. This means when you apply @bind attribute to an input type text element then the bindings will work only when the input element loses focus.

In the below code there is an “input type text” element which is bind to the President property using @bind attribute. The div element, which is placed below it, shows the president’s property value.

<input type="text" class="form-control" @bind="President" />
<div class="p-2 mb-2">President is: @President</div>

@code {
    private string President { get; set; }
}

Once you run this code and write a president’s name on the input element. You will notice the President’s value shown by the div is not instantaneous. It gets updated only when the text box loses it’s focus i.e. when you press tab key or click somewhere outside the text box.

This is because the onchange event is used by @bind attribute by default. This is the normal behaviour of onchange event which fires when the control loses focus. In the below video I have shown this thing.

Blazor Default binding event

Fortunately, Blazor has a mechanism to change this behaviour. You can use the attribute called @bind:event="oninput" to change the binding event to oninput.

The updated code now becomes:

@page "/Binding5"
<input type="text" class="form-control" @bind="President" @bind:event="oninput"/> 
<div class="p-2 mb-2">President is: @President</div>

@code {
    private string President { get; set; }
}

Run it and check the input value is displayed instantaneously.

Blazor bind with oninput event

Showing DateTime with Culture specific and Formatted values in Blazor

The values of the DateTime types can be shown in culture specific manner. They can also be formatted according you your needs.

In the below code I am using @bind:format attribute to show the DOB variables value in yyyy-MM-dd type. It will show DOB as – 2000-11-30.

@page "/Binding6"

<input type="text" class="form-control" @bind="DOB" @bind:format="yyyy-MM-dd" />

@code {
    private DateTime DOB = new DateTime(2000, 11, 30);
}

In the next code I am specifying the culture through @bind:culture attribute. There are 2 text boxes that shows sales time in en-gb and fr-FR cultures.

@using System.Globalization;

@page "/Binding7"

<input type="text" class="form-control" @bind="SaleTime" @bind:format="MMM-dd"  @bind:culture="CultureGB" />
<input type="text" class="form-control" @bind="SaleTime" @bind:format="MMM-dd" @bind:culture="CultureFR" />
 
@code {
    public DateTime SaleTime { get; set; } = DateTime.Parse("2020/05/15 07:20");
    public CultureInfo CultureFR { get; set; } = CultureInfo.GetCultureInfo("fr-FR");
    public CultureInfo CultureGB { get; set; } = CultureInfo.GetCultureInfo("en-gb");
}

The image shows their values formatted to culture specific.

Blazor bind format

You can download the full source codes:

Download

Conclusion

This long tutorial covered Blazor Event Handling in great details. We also covered Blazor Data Bindings and formatting values according to cultures. It will lead you to a strong foundation in Blazor. I hope you liked this tutorial so kindly share with your friends by clicking the social media icons given below.

SHARE THIS ARTICLE

  • linkedin
  • reddit
yogihosting

ABOUT THE AUTHOR

I hope you enjoyed reading this tutorial. If it helped you then consider buying a cup of coffee for me. This will help me in writing more such good tutorials for the readers. Thank you. Buy Me A Coffee donate

Comments

  1. Shivani Dattani says:

    Many thanks for making these tutorial series, this is very helpful for beginners like me. Just wanted to add a comment that Event and Data binding will not run in Asp.net core empty application without necessary reference inside _Imports.razor file. I needed to add following references then I am getting the result as this have.
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.JSInterop

Leave a Reply

Your email address will not be published. Required fields are marked *