Blazor FAQ - Data binding

Find answers for the most frequently asked questions
Expand All Collapse All

In two-way binding, data moves from the component to the UI and from the UI to the component class. Use the @bind attribute in the property to bind two ways in Blazor. By default, the bind attribute binds the data in the OnChange event. The OnChange event triggers when the element loses focus.

Follow these steps to achieve the two-way binding in Blazor.

<div>
    <input @bind="BindValue" @bind:event="oninput" />
</div>
<div>
    Binding Value : @BindValue
</div>

@code {
    public string BindValue { get; set; } = string.Empty;
}

Refer to this link for more details.

Permalink

To achieve two-way binding with the Select component in Blazor, you can use the @bind directive. Here’s an example of how you can implement two-way binding with the Select component:

Razor file

@page "/" 

<select @bind="selectedOption"> 
    <option value="option1">Option 1</option> 
    <option value="option2">Option 2</option> 
    <option value="option3">Option 3</option> 
</select> 

<p>You selected: @selectedOption</p> 
@code { 
    private string selectedOption = "option1"; 
} 

Refer to this link for more details.

View Sample in GitHub

Permalink

The input element value is updated by the @bind event in Blazor. To get the current input value, use the oninput native event of the input element and get the current input value.

<input type="text" @bind="@inputValue" @oninput="OnInputEvent" />

@inputValue

@code {
    private string inputValue = "Hello, world";
    private void OnInputEvent(ChangeEventArgs changeEvent)
    {
        inputValue = (string)changeEvent.Value;
    }
}
Permalink

You can refresh the Blazor component using the SignalR concept without reloading the page. When using SignalR, saving the changes in one page notifies the changes made to other clients. During the notification process, call the data loading method to reload the changes made to that component without reloading the entire page.

@code{

    public List<Order> Orders { get; set; }
    private HubConnection hubConnection;

    protected override void OnInitialized()
    {
        hubConnection = new HubConnectionBuilder()
        .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
        .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            LoadData(); //update the data
            StateHasChanged();//Refresh the component using updated data
        });

       await hubConnection.StartAsync();

    }

    protected async void LoadData()
    {
        //load all the orders from the server.
    }
}

Please refer to the documentation link for more details: https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr-blazor-webassembly?view=aspnetcore-3.1&tabs=visual-studio

Permalink

You can bind a specific format for the DateTime value by using the @bind:format attribute of the INPUT element and assign it with the supported date format string value.

Refer to the following code sample.

<input @bind="Value" @bind:format="@Format" />
 
@code{
    [Parameter]
    public DateTime Value { get; set; } = DateTime.Now;
 
    [Parameter]
    public string Format { get; set; } = "yyyy-MM-dd";
}

Permalink

To format the DateTime and numbers to the local culture, use the @bind:format attribute of the INPUT element that supports the date format string value .

Refer to the following code sample.

<input @bind="Value" @bind:format="@Format" />
 
@code{
    [Parameter]
    public DateTime Value { get; set; } = DateTime.Now;
 
    [Parameter]
    public string Format { get; set; } = "yyyy-MM-dd";
}
Permalink

You can  bind an input of type time in Blazor by using the @bind property to the time value and @bind:format property to specify the supported time format in the DOM input element.

Refer to the following code sample.

<input type="time" @bind="SomeTime" @bind:format="HH:mm"/>

@code {
    public DateTime SomeTime = new DateTime();
}
Permalink

String comparison with case insensitivity can be carried out using the  String.Compare method, where the first and second parameters are the strings to be compared and the third parameter is for ignoring case sensitivity (case insensitive comparison).

@page "/"

<h1>Case in-sensitive string comparision</h1>

<br />

<EditForm Model="@_stringCompare">
    String 1:
    <InputText id="string1" @bind-Value="_stringCompare.String1" />
    <br />
    String 2:
    <InputText id="string2" @bind-Value="_stringCompare.String2" />
    <br />
</EditForm>

<br />

<button @onclick="Compare">Compare</button>

<br />
<br />

<p>@Output</p>

<br />

@code {

    private StringCompare _stringCompare = new StringCompare();
    public string Output = "";

    public class StringCompare
    {
        public string String1 { get; set; }
        public string String2 { get; set; }
    }

    public async void Compare()
    {
        int CheckValue = String.Compare(_stringCompare.String1, _stringCompare.String2, true);
        Output = "Entered Strings are " + (CheckValue == 0 ? "" : "not ") + "Similar";
        await Task.Run(() => TimeOutMethod());
        Output = "";
        await Task.CompletedTask; 
    }

    void TimeOutMethod() => Task.Delay(3000).Wait();
}

View Sample in GitHub

Permalink

You can check/uncheck the checkbox in the Blazor programmatically by using the @bind parameter in the checkbox. Assign a Boolean property to @bind in the checkbox and toggle the Boolean property programmatically.

@page 
<input type="checkbox" @bind="@boolvalue" />
<br />
Checkbox: @val
<br />
<button class="btn btn-primary" @onclick="@ToggleCheckbox ">toggle</button>

@code {

public bool boolvalue { get; set; }
public string val;
 void ToggleCheckbox()
 {
        if (boolvalue)
        {
            val = "unchecked";
        }
        else
        {
            val = "checked";
        }
        boolvalue = !boolvalue;
}
}

Permalink

To set the active value on a select dropdown control, you must bind a property to the value in the select component and change that bind property in the event call

@page "/dropdown"


<select class="form-control" value="@listdefault" @onchange="@OnSelect" style="width:150px">
    @foreach (var template in templates)
    {
<option value=@template>@template</option>
     }
</select>

<h5>@selectedString</h5>
<select class="form-control" value="@citydefault" @onchange="@OnSelectCity" style="width:150px">
       @foreach (var template in citytemplates)
        {
   <option value=@template>@template</option>
}
</select>
<h5>@selectedCity</h5>
<button class="btn btn-primary" @onclick="@Change">Change</button>

@code {
    List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" };
    List<string> citytemplates = new List<string>();
    List<string> usa = new List<string>() { "Los-Angeles", "Florida", "Newyork", "Washington", "California" };
    List<string> china = new List<string>() { "Wuhan", "Beijing", "Shanghai", "Macau", "Taipei " };
    List<string> india = new List<string>() { "New-Delhi", "Mumbai", "Chennai", "Bangalore", "Hyderabad" };
    List<string> russia = new List<string>() { "Moscow", "Saint Petersburg", "Novosibirsk", "Yekaterinburg", "Kazan" };
    List<string> england = new List<string>() { "Birmingham", "Cambridge", "Manchester", "Leicester", "London" };
    string selectedString = "";
    string selectedCity = "";
    string listdefault = "India";
    string citydefault = "Mumbai";
    void OnSelect(ChangeEventArgs e)
    {
        if (e.Value.ToString() == "America")
        {
            citytemplates = usa;
        }
        else if (e.Value.ToString() == "China")
        {
            citytemplates = china;
        }
        else if (e.Value.ToString() == "India")
        {
            citytemplates = india;
        }
        else if (e.Value.ToString() == "Russia")
        {
            citytemplates = russia;
        }
        else
        {
            citytemplates = england;
        }
        selectedString = "Selected Country is: " + e.Value.ToString();

        StateHasChanged();
        Console.WriteLine("It is definitely: " + selectedString);
    }
    void OnSelectCity(ChangeEventArgs e)
    {
        selectedCity = "Selected CIty is: " + e.Value.ToString();
        Console.WriteLine("It is definitely: " + selectedString);
    }
    void Change(MouseEventArgs args)
    {
        listdefault = "Russia";
    }
    protected override void OnInitialized()
    {
        citytemplates = india;
        citydefault = "Chennai";
        base.OnInitialized();
    }
}

In the above sample, the city dropdown is changed based on the country selected in the country dropdown.

Permalink

The value property in the HTML <select> control can be utilized to set the default value. 

@page "/dropdown" 

<select class="form-control" value="@defaultValue.." @onchange="@OnSelect" style="width:150px"> 

@foreach (var template in templates)
{ 
<option value=@template>@template</option> 
} 

</select> 

<h5>@selectedString</h5> 

@code  
{ 
List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" }; 
string defaultValue = "India"; 
string selectedString = ""; 
void OnSelect(ChangeEventArgs e) 
{ 
         selectedString = "Selected Country is: " + e.Value.ToString(); 
} 
} 
Permalink

To retrieve a selected value from the select control, you can use either the @bind or @onchange event.

//using @bind

@page "/dropdown"
<select class="form-control" @bind="@selectedString" style="width:150px">
         @foreach (var template in templates)
         {
                 <option value=@template>@template</option>
         }
</select>

<h5>Selected Country is: @selectedString</h5>

@code {
List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" };
string selectedString = "America";
    }
//using @onchange event

@page "/dropdown"

<select class="form-control"  @onchange="@OnSelect" style="width:150px">
         @foreach (var template in templates)
         {
                 <option value=@template>@template</option>
         }
</select>

<h5>Selected Country is: @selectedString</h5>

@code {
List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" };
string selectedString = "America";

void OnSelect (ChangeEventArgs e)
{
        selectedString = e.Value.ToString();
        Console.WriteLine("The selected country is : " + selectedString);
}
    }

Permalink

To get the checkbox value when it is checked or unchecked use the onchange event by calling a method in onchange event using lambda expression and passing the checkbox value to it.

@foreach (var check in CheckBoxList())
{
 <input class="custom-checkbox" type="checkbox" @onchange="eventArgs => { CheckboxClicked(check, eventArgs.Value); }" />
@check
 <br />
}

@code {

public List<string> CheckBox { get; set; } = new List<string>();
void CheckboxClicked(string CheckID, object checkedValue)
 {
if ((bool)checkedValue)
{
        if (!CheckBox.Contains(CheckID))
        {
                CheckBox.Add(CheckID);
         }
 }
 else
 {
        if (CheckBox.Contains(CheckID))
         {
                CheckBox.Remove(CheckID);
         }
 }
 }

public List<String> CheckBoxList()
{
List<String> checkBox = new List<String>();
checkBox.Add("CheckBox 1");
checkBox.Add("CheckBox 2");
return checkBox;
}
}
Permalink

To bind properties to a list in Blazor, you can use the @foreach loop and the @bind directive. Here’s an example: 

@page "/" 

<h3>List Binding Example</h3> 
<ul> 
    @foreach (var item in itemList) 
    { 
        <li> 
            <input type="text" @bind="@item.Name" /> 
        </li> 
    } 
</ul> 

<button @onclick="AddNewItem">Add Item</button> 

@code { 
    List<ItemModel> itemList = new List<ItemModel>(); 
    void AddNewItem () 
    { 
        itemList.Add(new ItemModel()); 
    } 
    public class ItemModel 
    { 
        public string? Name { get; set; } 
    } 
} 

View Sample in GitHub  

Permalink

This ObservableCollection (dynamic data collection) provides notifications when items are added, removed, and moved. The implemented INotifyCollectionChanged provides notifications when dynamic changes of adding, removing, moving, and clearing the collection occur. The implementation of INotifyPropertyChanged notifies when property value has changed in client side. Here, Order class implements the interface of INotifyPropertyChanged and it raises the event when CustomerID property value was changed.

[index.razor]

@page "/"
@using System.Collections.ObjectModel
@using System.ComponentModel


<h2>Observable Collections</h2>
<div class="d-flex flex-row my-2">
    <button id="add" @onclick="AddRecords">Add Data</button>
    <button id="del" @onclick="DelRecords">Delete Data</button>
    <button id="update" @onclick="UpdateRecords">Update Data</button>
</div>
<table class="table">
    <thead>
        <tr>
            <th>Customer ID</th>
            <th>Order ID</th>
            <th>Frieght</th>
            <th>Order Date</th>
            <th>Ship Country</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var data in GridData)
        {
            <tr>
                <td>@data.CustomerID</td>
                <td>@data.OrderID</td>
                <td>@data.Freight</td>
                <td>@data.OrderDate</td>
                <td>@data.ShipCountry</td>
            </tr>
        }
    </tbody>
</table>

@code{

    public ObservableCollection<OrdersDetailsObserveData> GridData { get; set; }

    protected override void OnInitialized()
    {
        GridData = OrdersDetailsObserveData.GetRecords();
    }

    public void AddRecords()
    {
        GridData.Add(new OrdersDetailsObserveData(32341, "ALFKI", 4343, 2.3 * 43, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
    }

    public void DelRecords()
    {
        GridData.Remove(GridData.First());
    }

    public void UpdateRecords()
    {
        var a = GridData.First();
        a.CustomerID = "Update";
    }

    public class OrdersDetailsObserveData : INotifyPropertyChanged
    {
        public OrdersDetailsObserveData()
        {
        }
        public OrdersDetailsObserveData(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
        {
            this.OrderID = OrderID;
            this.CustomerID = CustomerId;
            this.EmployeeID = EmployeeId;
            this.Freight = Freight;
            this.ShipCity = ShipCity;
            this.Verified = Verified;
            this.OrderDate = OrderDate;
            this.ShipName = ShipName;
            this.ShipCountry = ShipCountry;
            this.ShippedDate = ShippedDate;
            this.ShipAddress = ShipAddress;
        }
        public static ObservableCollection<OrdersDetailsObserveData> GetRecords()
        {
            ObservableCollection<OrdersDetailsObserveData> order = new ObservableCollection<OrdersDetailsObserveData>();
            int code = 10000;
            for (int i = 1; i < 2; i++)
            {
                order.Add(new OrdersDetailsObserveData(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
                order.Add(new OrdersDetailsObserveData(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123"));
                order.Add(new OrdersDetailsObserveData(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bol�var #65-98 Llano Largo"));
                order.Add(new OrdersDetailsObserveData(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7"));
                order.Add(new OrdersDetailsObserveData(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S."));
                code += 5;
            }
            return order;
        }

        public int OrderID { get; set; }
        public string CustomerID
        {
            get { return customerID; }
            set
            {
                customerID = value;
                NotifyPropertyChanged("CustomerID");
            }
        }
        public string customerID { get; set; }
        public int EmployeeID { get; set; }
        public double Freight { get; set; }
        public string ShipCity { get; set; }
        public bool Verified { get; set; }
        public DateTime OrderDate { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public string ShipName { get; set; }

        public string ShipCountry { get; set; }

        public DateTime ShippedDate { get; set; }
        public string ShipAddress { get; set; }

        private void NotifyPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

In the sample, we have add, delete and update buttons where the observable data for the table will be populated, removed or updated through the button click.

Permalink

We can get child component values in the parent component by creating a reference to the child component using the @ref directive in the Parent component. Using the reference instance, you can access the child component values in the parent.

In the following example, textbox refers to the TextBoxComponent (child component) instance. Using textbox, we can access the properties and values in the Parent component.

[TextBoxComponent.razor]

<div class="form-group row mb-2">
    <label class="col-md-3 col-form-label"
           for="Name">@FieldName</label>
        <div class="col-md7">
            <input class="form-control"
                   type="text"
                   placeholder="@FieldName" value="@Value" @oninput="OnValueChanged" maxlength="@MaxLength" />
        </div>
    </div>

    @code {
        [Parameter]
        public string Value { get; set; }

        [Parameter]
        public string FieldName { get; set; }

        [Parameter]
        public int MaxLength { get; set; } = -1;

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

        string LengthString;
        int TextLength;

        protected override void OnInitialized()
        {
            TextLength = Value.Length;
            LengthString = (MaxLength == -1) ? "Unlimited" : MaxLength.ToString();
        }

        private Task OnValueChanged(ChangeEventArgs e)
        {
            Value = e.Value.ToString();
            TextLength = Value.Length;
            return ValueChanged.InvokeAsync(Value);
        }
    }
[Parent.razor]

@page "/parent"

<TextBoxComponent @ref="textbox" @bind-Value="name" FieldName="Name" MaxLength="20" />
<TextBoxComponent @bind-Value="address" FieldName="Address" />
<button @onclick="Click">Click </button>
@code {
    TextBoxComponent textbox;
    string name = "Rafael Nadal";
    string address = "New York";
    private void Click()
    {
        var fNme = textbox.FieldName;
        var maxLen = textbox.MaxLength;
    }
}  
Permalink

Two-way binding is having a bidirectional data flow, i.e., passing the value from the property to the UI and then from the view (UI) to the property. Blazor provides support for two-way binding using the bind attribute.

Syntax for creating two-way binding property:

@bind-{Parameter_name}={Variable_name}

For e.g.., in InputDate, a form component can be used to achieve two-way data binding with input date values in a Blazor application.

Refer to the following code for more details.

<EditForm Model="@_test">
    <InputDate @bind-Value="_test.DateValue" />
</EditForm>

<br />

<p>Selected Date: @_test.DateValue.ToLongDateString()</p>

@code {
    
    public class TestClass
    {
        public DateTime DateValue { get; set; }
    }

    private TestClass _test = new TestClass();
}

In this example code, when the value of _test.DateValue is changed in the code or user changes the date in the InputDate component, the same will be reflected in the paragraph, “Selected Date”.

Permalink

One-way (unidirectional) binding is all about moving data in one direction from the “Parameter/Property” to the UI (components). You just need to add the @ symbol to the variable name (for example, @yourVariable).

For example, one-way binding with an input date value can be achieved using the InputDate component (form component in Blazor) as follows in an application.

<EditForm Model="@_test">
    <Input type="Date" Value="@_test.DateValue" />
</EditForm>

@code {
    
    public class TestClass
    {
        public DateTime DateValue { get; set; }
    }

    private TestClass _test = new TestClass();
}

In this example, the property DateValue in _test class is bound to the InputDate component’s value property using the value attribute. A form is defined by the EditForm component.

Permalink

You have to use the bind attribute to reflect the DOM element value in the C# property.

<p>
    @* This is the input element *@
    Enter your name: <input type="text" @bind=@name />

    <button @onclick="@PrintName">Print Name</button>
</p>
@code {
    string name;

    private void PrintName()
    {
      Console.WriteLine(name); // Here the entered name will be printed.
    }
}
Permalink

The value of an input element is updated in the wrapper with the change events of elements in Blazor. To get the current value for each character input, you must use the oninput event of the input element. This can be achieved by binding the oninput event (native event) using the @bind:event=oninput.

 @CurrentValue
 <input type="text" @bind="@CurrentValue" @oninput="@((e) => { CurrentValue=(string)e.Value;})" />
  
 @code {
     private string CurrentValue {get;set;} = "blazor";
 } 
Permalink

The format-value attribute is used to format the DateTime strings. Other formats, like currency or number formats, are currently not available.

 <input @bind="@StartDate" format-value="yyyy-MM-dd" />
    
   @code {
       private DateTime   StartDate { get; set; } = new DateTime(2020, 1, 1);
   }     

Refer to the link format strings to learn more about formatting.

Permalink

DOM elements are hidden using the hidden attribute. You can conditionally use any .NET parameter to set this attribute to hide the DOM elements.

@page "/"
    
   <p hidden="@IsShow">I am Blazor</p>
    
   <button @onclick="@Show">Show/Hide</button>
  
 @code {
       private bool IsShow   {get;set;} = false;
       private void Show()
       {
           IsShow =   !IsShow;
       }      
 } 
Permalink

DOM attributes are rendered based on .NET parameters. If the parameter value is true, the attribute is rendered minimized, otherwise it’s not. Refer to the code example to render the checked attribute conditionally.

 <input type="checkbox" checked="@IsChecked">
  
 @code {
     [Parameter]
     public bool IsChecked { get; set; }
 } 
Permalink

By default, Blazor detects changes and reflects them in the UI automatically. However, there might be a situation where we have to manually trigger changes. StateHasChanged informs the component that its state has changed, but it does not render the component. The component will decide when to render itself.

You can’t do that in a synchronous method, so you should async your code to give the component a chance to render.

@page "/"
  
 @using System.Threading;
  
 <button type="button" @onclick="@PlaceOrder_Clicked" disabled="@DisablePlaceOrderButton">@Title</button> 
@code{
     private bool DisablePlaceOrderButton { get; set; } = false;
  
     public string Title { get; set; } = "Click Button";
  
     private async Task PlaceOrder_Clicked()
     {
  
         await DisablePlaceOrder();
         DisablePlaceOrderButton = false;
         Title = "State Has Changed";
  
     }
  
     async Task DisablePlaceOrder()
     {
         DisablePlaceOrderButton = true;
         Title = "Wait...";
         await Task.Delay(3000);
  
         StateHasChanged();
     }
 } 
Permalink

You can bind events to DOM elements started with the on<event> with a delegate-type value. The attribute’s name always starts with “on.” In the following code example, the “UpdateHeading” event is triggered when the button is clicked.

<button class="btn   btn-primary" @onclick="@UpdateHeading">
       Update heading
   </button>
    
 @code {
       private void UpdateHeading(MouseEventArgs e)
       {
           ...
       }
   }  

Refer to this Blazor documentation for more information.

Permalink

Two-way is having a bi-directional data flow, i.e., passing the value from the property to the UI and then from the view (UI) to the property as well The synchronization of data flow between model and view is achieved using the bind attribute in Blazor. Refer to the following code example for two-way data flow.

@page "/"
    
   Enter your name: <input type="text" @bind="@Name" /><br />
    
   <h2>Hello, @Name!</h2>
    
   @code {
      
       private string Name { get; set; } = "Blazor";      
 } 
Permalink

You can bind the data with DOM element using the “@” prefix with a C# parameter. Refer to the following example for one-way data binding.

@page "/"
  
 <h2>Hello, @Name!</h2>
  
 @code {
    
     private string Name { get; set; } = "Blazor";
 }  
Permalink

Data binding synchronizes the data between the view and model. In other words, it binds the C# parameter with DOM elements and vice versa.

Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.