Blazor .NET 8 - Enhanced Form Navigation

22/11/2023
C#Blazor.NET

There are many new cool features with .NET 8 and Blazor in particular. In this blog post, I want to highlight a feature that I believe is very useful in the new context Blazor is living.

Blazor Forms and Navigation

To wrap up why Blazor is now a big deal (and probably bigger than ever): Server Side Rendering and the ability to just deliver static content! I briefly summarize from my own blog post article from a few months ago:

Now meet server-side rendering: This is kind of a special case of the server hosting model. Here, the server renders the whole DOM and sends it to the client. The client only renders the DOM. That is it. No SignalR, just static content. That is amazing for read-only content with zero interactions, but obviously falls short if you need to handle button clicks.

So if you have a read-only site - that is a game changer for you. But wait - let's examine my last sentence: but obviously falls short if you need to handle button clicks. That is not true! Here is where Enhanced Form Navigation comes into play. Blazor gives you the ability to handle forms in a "SPA" manner without utilizing either InteractiveServer or InteractiveWebAssembly mode. This can be a huge deal! Let's see how it works.

Example

For our example, I use the default template for Blazor shipped with .NET 8, but one big adjustment: I disable any interactiity mode.

builder.Services.AddRazorComponents();

...

app.MapRazorComponents<App>();

No interactivity, as you can see. Now let's create a simple page that holds some recipes, ingredients or what not and a form element that we will utilize as an input:

@page "/"

<form data-enhance>
    <input name="query" placeholder="Search" value="@Query" />
    <button>Search</button>
</form>

<ul>
    @foreach (var item in _filteredEntries)
    {
        <li>@item</li>
    }
</ul>

@code {
    [SupplyParameterFromQuery]
    public string Query { get; set; }

    public List<string> _entries = ["Chocolate", "Vanilla", "Strawberry"];
    private List<string> _filteredEntries;

    protected override void OnInitialized()
    {
        _filteredEntries = !string.IsNullOrEmpty(Query) 
            ? _entries.Where(x => x.Contains(Query)).ToList() 
            : _entries;
    }
}

Two major things here: We have a Query-Parameter that gets filled via the SupplyParameterFromQuery-Attribute. This is a feature that allows you to supply parameters from the query string. The second thing is the form-element. It has a data-enhance-attribute. This is the magic that allows us to use the form in a SPA-like manner. Let's see what happens if we "search" something:

Video

Keep in mind, that we use the same name in the form/input as the query string - so there is no big magic happening here. We have a form that does a request. As you can see in the video, blazor.web.js does make a fetch request and dynamically patches the DOM! There is no additional content downloaded - or in the worst case, the whole page again!

Resources

  • Source code to this blog post: here
  • All my sample code is hosted in this repository: here
3
An error has occurred. This application may no longer respond until reloaded. Reload x