Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor Checkbox two-way binding and change event

What is the correct way to bind a checkbox and have an event fire when that checkbox changes? I have tried a couple of different ways all not working exactly as I had hoped. Note the checkbox is in a component.

<input type="checkbox" checked="@IsChecked" @onchange="CheckboxChanged">
@code{
      [Parameter]
      public bool IsChecked { get; set; } = true;
      private void CheckboxChanged()
      {
           Console.WriteLine($"Checkbox changed {IsChecked}");
      }
}

When the page loads it reads the value that is given to IsChecked, and when the CheckBox is checked the method fires. However, the value for IsChecked is not updated. Then if the binding value for IsChecked is changed outside of the component, the method does not fire but the value for IsChecked is changed (should note that UI is updated correctly).

I figured I needed an actual bind like this:

<input type="checkbox" @bind="IsChecked" @onchange="CheckboxChanged" >

However, this gives an error that onchange is used two or more

<input type="checkbox" @bind="IsChecked" @onclick="CheckboxChanged" >

When the user clicks the checkbox it does fire the method however, IsChecked is at the old value (I am assuming the click happens before the bind). Then if the value for IsChecked is changed outside of the component, once again the method does not fire.

What is the correct way?

like image 262
Xaphann Avatar asked Sep 05 '25 12:09

Xaphann


2 Answers

There are two issues with your code/component:

  1. You should not modify [Parameters] within your code. These are set whenever the component updates.
  2. The bind uses the OnChanged event to update isChecked, so you can't also use it.

Here's commented code that works.

  1. Uses an internal field to hold the checkbox state.
  2. Wired up the OnInput event.
@page "/"
<input type="checkbox" checked="@isChecked" @oninput="CheckboxChanged">

@code{
    [Parameter]
    public bool IsChecked { get; set; } = true;

    // Internal field holding checkbox state
    private bool isChecked;

    // updates the internal value whwenever the component is updated
    // You may not want that??
    protected override void OnParametersSet()
    {
        isChecked = this.IsChecked;
    }

    private void CheckboxChanged(ChangeEventArgs e)
    {
        // get the checkbox state
        var value = e.Value;
        Console.WriteLine($"Checkbox changed {IsChecked}");
      }
}
like image 107
MrC aka Shaun Curtis Avatar answered Sep 09 '25 08:09

MrC aka Shaun Curtis


As of .NET 7 you can use the @bind-value:after to tap into the change event after it's happened.

<input type="checkbox" @bind-value="@IsChecked" @bind-value:after="CheckboxChanged">

@code{
      [Parameter]
      public bool IsChecked { get; set; } = true;
      private void CheckboxChanged()
      {
           Console.WriteLine($"Checkbox changed {IsChecked}");
      }
}
like image 45
aryeh Avatar answered Sep 09 '25 10:09

aryeh