Blazor Bites - Data Binding & Events

Blazor Bites Series


Post valid for: Blazor 0.4.0
Please remember that Blazor is an experimental project and is going to be changing regularly. IT IS NOT PRODUCTION READY.


Data Binding

Displaying data in Blazor is really simple and if you have any experience with Razor then this should all be very familiar to you. If not, don't worry it's really easy to pick up.

One-way binding

This is used for printing values into your Razor templates. These values could be strings such as a title in a <h1> tag or items in a list. But it can also be used to dynamically inject values into the HTML; such as the name of a CSS class on an element.

Example
@page "/onewaybinding"

<h1>@title</h1>

Welcome to my one-way binding example. Here's a list of colours.

<ul>
    @foreach (var colour in colours)
    {
        <li>@colour</li>
    }
</ul>

@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    <p class="@weekendFontStyle">It's the weekend!</p>
}
else
{
    <p>It's @DateTime.Now.DayOfWeek.ToString()</p>
}

functions {

    private string title { get; set; } = "Welcome to one-way binding"
    private List<string> colours { get; set; } = new List<string> { 
        "Red", "Blue", "Green", "Yellow" 
    };  
    private string weekendFontStyle { get; set; } = "party-time";

}

Two-way Binding

Now you know how to print out values to a Razor template. But what if you would like a user to be able to update those values? This is where two-way bidning comes in. Blazor uses a method called bind to achieve this. In the current version of Blazor bind can only support string and boolean types. If you wish to use any other types then you will have to manually convert from and to string in the properties getter and setter.

Formatting Bindings

If you wish to format a bound value you can use the format-value attribute. At the moment this is limited to just the DateTime type. With it you can provide a format string to specify how .NET values should be bound to attribute values.

Example
<h1>Record your current favourite colour</h1>

<p>
    <input bind="@Name" />
</p>

<p>
    <select bind="@FavouriteColour">
        <option>Red</option>
        <option>Blue</option>
        <option>Green</option>
        <option>Yellow</option>
    </select>
</p>

<p>
    <input bind="@DateRecorded" format-value="dd/mm/yyyy" />
</p>

<hr />

<p>Hi @Name</p>
<p>Your favourite colour on @DateRecorded was @FavouriteColour</p>


@functions {

    public string Name { get; set; }
    public string FavouriteColour { get; set; }

    private DateTime dateRecorded = DateTime.Now;
    public string DateRecorded
    {
        get => dateRecorded.ToShortDateString();
        set => DateTime.TryParse(value, out dateRecorded);
    }
    
}

Events

Binding to events in Blazor was given a big upgrade from 0.1.0 to 0.2.0. In the first preview of Blazor there were just three events available - onclick, onchange and onkeypress. With 0.2.0+ this is no longer the case and we have access to any event we need.

The new syntax looks like this on[eventname] and is used as an attribute in your markup. This attribute takes a delegate which is registered with the event. For example, <input onkeyup="@KeyUp" /> will call the KeyUp method whenever the onkeypress event is trigged. In the KeyUp method you are able to accept UIEventArgs which will give you access to some details of the event. There are some more specific args available for certain events such as UIMouseEventArgs but these are very limited. There will be more available in upcoming releases.

You can also define your own events, for example, when doing component to component communication but I'll cover that in a future post.

Example
<input onkeypress="@LogKeyPressed" />

<ul>
    @foreach (var key in keyLog)
    {
        <li>@key</li>
    }
</ul>

@functions {
    
    private List<string> keyLog { get; set; } = new List<string>();

    void LogKeyPressed(UIEventArgs eventArgs)
    {
        keyLog.Add(((UIKeyboardEventArgs)eventArgs).Key);
    }
}
Example
// Using a lambda

<button onclick="@(e => buttonClicks++)">Click me</button>

<p>You clicked the button @buttonClicks times</p>


@functions {

    private int buttonClicks { get; set; }
    
}