Blazor Events and Data Bindings

Blazor Events and Data Bindings

Blazor can respond to events like button click, select change, text change on text box, clipboard events, mouse events and so on. This process is known as Event Handing. For example, the following code shown a button having an onclick event.

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 cover every type of file and their importance in Blazor.
<button @onclick="SendMail">
    Send Email
</button> 
@code {
    private void SendMail()
    {
        ...
    }
}

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.

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

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

The EventArgs Classes and the Events They Represent

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:

<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 information like:

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

In fact, there are just 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).

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

Common HTML tags and their Blazor Events

Now I will show you some examples of how you can use HTML tags like buttons, input tags, select tags, checkbox and radio buttons with Blazor Events. Note that my Blazor app is created with basic configurations which I did in my previous tutorial.

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.

<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.

When the user types in the text box (input type text) and changes focus, then onchange event is fired and the MyName property 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 the “h3” tag:

@MyName

This is how it will work:

blazor onchange textbox
Single Handler for Events from Multiple Elements

To avoid code duplication, you can use a Single Hander method for receive 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 onchange events of text boxes.

<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 use 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:

Single Handler for Events 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 onchange event works well with the HTML Select tag to. Now place select tag with “onchange” event as – @onchange="Option". See the below code:

<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 called “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 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:

<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:

blazor onchange checkbox

Example: Radio Button “onchange” event

Radio buttons can be used with 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 like here I have given them the same name “sex”.

<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 event for the button.

Now suppose you add onclick event to the button which does some work (like increasing the counter by 1). You will notice that in this case, when you click the button, the form will get submitted but the button’s onclick event will not be executed. I have shown this problem in the below code:

<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">Increase Counter</button>
    </div>
</form>

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

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

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

Preventing Default Events
“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.

<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:

onclick 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:

<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:

preventing Event Propagation
Note that event propagation happens from child till to root element of the DOM tree.
“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:

<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

You can bind html controls with C# value using Data Bindings feature of Blazor. You can simple bind the value attribute of the HTML control/tag with the C# property and this will show the C# property’s value inside the control. For example, in the below code I am 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, you can use the value attribute in other html controls like select tag, radio button, etc. Let us take an example of the select control.

In the below given code, there is a select tag that let you select 3 frameworks given in it’s options. 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 “Frameworks” property’s value inside it. This code is given below.

<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.

select value attribute

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.

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:

<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.

bind attribute 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.

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:

<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. Then you should use this apprach where you call a property with @onbind attribute and on the property set code, you do your task. See the below code which shows this thing.

<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>

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. One 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.

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:

<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.

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.

<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.

<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.

bind format

You can download the full source codes:

Download

Conclusion

This long tutorial covers how to work with event in Blazor. You also covered 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 -

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

Leave a Reply

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