Blazor Bindings By Example - Part 2

Examining String Bindings

Blazor Bindings By Example - Part 2

Introduction

This is the second part of the series Blazor Bindings By Example in which we explore how to bind some of the properties in our example model, which we created in part 1 of this series.

In this part we look at binding string properties, namely the Name property.

As a reminder our model looks like this:

namespace BlazorBindingExamples.Models
{
    public class Model
    {
        public Model(Guid id)
        {
            Id = id;
        }

        public Guid Id { get; init; }
        public string? Name { get; set; }
        public Gender? Gender { get; set; }
        public string? Nationality { get; set; }
        public int? Age { get; set; }
        public decimal? Salary { get; set; }
        public MarketingOption? MarketingOptions { get; set; }
    }
}

All the code for this series is available from GitHub.

Extend Visual Studio Project

First of all, let's extend the Visual Studio example project to include a new page dedicated to various ways to bind the Name property and add a left 'NavLink' item.

Add a new Page called "StringBinding" for both the view and the viewmodel:

  • Pages/StringBinding.razor
  • Pages/StringBinding.razor.cs

And then add a new NavLink entry within the shared NavMenu below the existing "Home" menu:

  • Shared/NavMenu.razor

StringBinding.razor

@page "/stringbinding"

<PageTitle>Blazor Bindings By Example - String Binding</PageTitle>

<h1>Blazor Example Bindings - String Binding</h1>

@if (!Initialised)
{
    <p>Loading...</p>
}
else
{
    <!-- Put the binding examples here //-->
}

StringBinding.razor.cs

using BlazorBindingExamples.Models;
using Microsoft.AspNetCore.Components;

namespace BlazorBindingExamples.Pages
{
    public partial class StringBinding : ComponentBase
    {
        public bool Initialised { get; set; } = false;
        public Model Model { get; private set; }

        protected override async Task OnInitializedAsync()
        {
            Model = new(Guid.NewGuid());
            Model.Name = "Stuart Wells";

            await base.OnInitializedAsync();

            // Set this when fully initialised as we use this to prevent premature rendering
            Initialised = true;
        }
    }
}

NavMenu.razor

<div class="nav-item px-3">
    <NavLink class="nav-link" href="stringbinding">
        <span class="oi oi-signpost" aria-hidden="true"></span> String Binding
    </NavLink>
</div>

Binding The Name Property

The Name property is a nullable string which is read/write:

public string? Name { get; set; }

It has been initialised with my name, "Stuart Wells", and can be bound in multiple ways:

  • read-only element content
  • read-only attribute content
  • conditional read-only content
  • editable input field

Element Content

Bind the string value to a simple read-only html element content such as a paragraph <p> or <span> in line using the @Model reference:

@Model.Name

An example in a paragraph would be:

<p>The name of the client is '@Model.Name'.</p>

Which would present as:

The name of the client is 'Stuart Wells'.

Tip: if you find yourself wanting to use the @ character, you can escape this t prevent it being interpreted as a viewmodel reference by prefixing it with another @:

<p>The variable @@Model.Name contains the value "@Model.Name".</p>

Produces

The variable @@Model.Name contains the value "Stuart Wells".

Attribute Content

Bind the string value to a read-only html attribute content such as a paragraph title <p title=""> using the @Model reference:

<p title="About @Model.Name">The title contain the value of the Name property.</p>

Which could look like this, with the tooltip showing the title:

screenshot of a paragraph with a title attribute bound to the name property

Conditional Content

Sometimes the content we need to write out may need some conditional logic. One could argue here that we should not be using conditional logic like this in the view anyway and that any logic should be in the viewmodel and the view should just bind the result, but for demonstration purposes we can bind script expressions inline like this:

<p title="@(string.IsNullOrWhiteSpace(Model.Name) ? "Unknown Name" : "About " + Model.Name )">
    The property Name does @(string.IsNullOrWhiteSpace(Model.Name) ? "not " : string.Empty ) have a value.
</p>

Which produces this when we have a value:

screenshot of a paragraph with a title attribute bound to the name property with a value

And this when we don't have a value:

screenshot of a paragraph with a title attribute bound to the name property without a value

Editable Input

So far we have seen how to bind in a property that is read-only. If the underlying property value changes, the read-only value will update, but we need to have a two-way binding using an input field to capture the change.

Using an input field on its own (outside a form) the value will bind when the field is exited (loses focus) or enter/return is pressed:

<label for="opt4">Name:</label>
<input id="opt4" type="text" @bind-value="Model.Name">
<p>The value of Name is "@Model.Name".</p>

Which produces

screenshot of an input field having been edited

Summary

In this article, the second article in the series "Blazor Bindings By Example", we have examine how a simple string property can be bound to html content and how it can be edited using two-way bindings.

In the next article, we will examine the Gender property, which is an enumeration.

Did you find this article valuable?

Support Stuart Wells by becoming a sponsor. Any amount is appreciated!