INotifyPropertyChanged behavior in Blazor Components

By design, when you build a server-side Blazor app, and you pass parameters to a component when those parameters change inside the component the changes are not reflected in the host. With a little hack, we can make that happen. It’s INotifyPropertyChanged all over again!

This gem came from my online 8-hour Blazor Workshop. You can purchase the video and materials or sign up for the next class.

In Visual Studio 2019 (or higher) create a new Blazor app called NotifyComponentDemo.,

Add a new class called Customer with two string properties: Name and Email.

Right-click on the Pages folder and select Add / New Item.

Select Web from the list on the left and then Razor Comopnent from the list.on the right.

Name the component Editor and replace with the following:

<div style="background-color:lightgray;">
    <div style="padding:1vw;">
        Name: <br />
        <input @bind="@Customer.Name" @bind:event="oninput" />
        <br/><br/>
        Email: <br />
        <input @bind="@Customer.Email" @bind:event="oninput" />
    </div>
</div>

@code {

    [Parameter]
    public Customer Customer { get; set; }

}

Now open Index.razor from the Pages folder and replace wiht the following:

@page "/"
<Editor Customer="Customer" />
<br />
<br />
Name: @Customer.Name
<br />
Email: @Customer.Email
<br />


@code {

    Customer Customer = new Customer();

    protected override void OnInitialized()
    {
        Customer = new Customer {
            Name = "Ben Goofin",
            Email = "ben@bengoofin.com"
        };
    }
}

Our component accepts a customer object as a parameter. It allow you to edit the name and email properties.

Press F5 and run. One might expect that as you edit the values, your Index page would show the changes as you type, especially since we are using the @bind:event=oninput syntax.

Not so, and this is by design.

In order to make this happen we have to first capture the keystrokes in the input boxes. Change the input tags to the following:

        Name: <br />
        <input @bind="@Customer.Name" 
               @bind:event="oninput" @onkeyup="KeyPressed" />
        <br/><br/>
        Email: <br />
        <input @bind="@Customer.Email" 
               @bind:event="oninput" @onkeyup="KeyPressed"  />

Now we need to handle that keypress event, but what should we do when a key is pressed?

We need to add an event handler to notify the host (Index.razor) that the state of the component (namely the Customer object) has changed.

Add the following code to the code block in the component:

    [Parameter]
    public EventCallback<string> ComponentDataUpdated { get; set; }

    async Task KeyPressed(KeyboardEventArgs args)
    {
        await ComponentDataUpdated.InvokeAsync("");
    }

Go back to the host (Index.razor) and modify as follows:

@page "/"

<Editor Customer="Customer" ComponentDataUpdated="ComponentUpdated" />
   
<br />
<br />
Name: @Customer.Name
<br />
Email: @Customer.Email
<br />


@code {

    Customer Customer = new Customer();

    protected override void OnInitialized()
    {
        Customer = new Customer {
            Name = "Ben Goofin",
            Email = "ben@bengoofin.com"
        };
    }

    void ComponentUpdated(string args)
    {
        StateHasChanged();    
    }
}

So, on every key press our component raises the ComponentUpdated event, which we handle in the host page in a like-named method, ComponentUpdated. The string argument is ignored but necessary.

All our code does is call StateHasChanged() and magically, Blazor updates the UI in the host that displays properties of the Customer object.

Voila'



Carl Franklin has been a key leader in the Microsoft developer community since the very early days when he wrote for Visual Basic Programmers Journal. He authored the Q&A column of that magazine as well as many feature articles for VBPJ and other magazines. He has authored two books for John Wiley & Sons on sockets programming in VB, and in 1994 he helped create the very first web site for VB developers, Carl & Gary's VB Home Page.

Carl is a Microsoft MVP for Developer Technologies, and co-host of .NET Rocks!, one of the longest running podcasts ever (2002). Carl is also an accomplished musician and audio/video producer. He started Pwop Studios in 1999 as a record label for his first album, a collaboration with his brother Jay: Strange Communication. Franklin Brothers released Lifeboat To Nowhere in 2011, which has met with rave reviews. In 2013, Carl released his first solo album, Been a While, which features a tune with John Scofield on guitar, as well as an incredible group of musicians local to New London, CT.

Pwop Studios is a full-service audio and video post production studio in New London, CT, where Carl records and produces the podcasts as well as music and video projects - both for himself, Franklin Brothers Band, and the public.