Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor - detect when any form value changes

Tags:

blazor

In a Blazor form, I'd like to be able to detect whenever a form value has changed, and set a boolean value as a result.

Here is some code to illustrate how I am currently doing it:

<EditForm Model="Person" OnValidSubmit="OnSubmitValidateForm">
   <div class="form-group">
      <label>First Name</label>
      <input type="text" value="@Person.FirstName" @onchange="OnFirstNameChanged" />
   </div>
   <div class="form-group">
      <label>Surname</label>
      <input type="text" value="@Person.Surname" @onchange="OnSurnameChanged" />
   </div>
   <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

@code {
   Person Person = new Person();
   bool dataChanged = false;
  
   void OnFirstNameChanged(ChangeEventArgs e)
   {
      Person.FirstName = e.Value.ToString();
      dataChanged = true;
      StateHasChanged();
   }
   
   void OnSurnameChanged(ChangeEventArgs e)
   {
      Person.Surname = e.Value.ToString();
      dataChanged = true;
      StateHasChanged();
   }
}

In the above form I have two fields - "FirstName" and "Surname" which are properties of the "Person" class. There is an input textbox bound to each property. Whenever the value changes in either textbox, the respective method is called which will update the property value, and also indicate that the form data has changed.

It seems excessive to have an event handler for every form item, when in each case all it's really doing is what @bind="" would do, plus setting dataChanged to true.

My question is, whilst the approach works, it seems like I have to write quite a lot of extra code. Is there a better way to handle this?

like image 273
Laurence Frost Avatar asked Apr 21 '26 09:04

Laurence Frost


2 Answers

You should use the native Forms Components, such as InputText, InputDate, etc., and implement the OnFieldChanged event. The OnFieldChanged event is raised for each field in the model.

Code sample

@page "/"

@using Microsoft.AspNetCore.Components.Forms;

<EditForm EditContext="@ValidationContext.EditContext" 
            OnValidSubmit="HandleValidSumit">
    <DataAnnotationsValidator />

    <div class="form-group">
        <label for="name">FirstName: </label>
        <InputText Id="FirstName" Class="form-control" @bind- 
      Value="@person.FirstName"></InputText>
        <ValidationMessage For="@(() => person.FirstName)" />

    </div>
    <div class="form-group">
        <label for="body">Surname: </label>
        <InputText Id="body" Class="form-control" @bind- 
       Value="@person.Surname"></InputText >
        <ValidationMessage For="@(() => person.Surname)" />
    </div>
    <button type="submit" class="btn btn-success">Submit</button>
</EditForm>


@code
{
   Person person = new Person();
   protected override void OnInitialized()
   {
        EditContext = new EditContext(person);
        EditContext.OnFieldChanged += EditContext_OnFieldChanged;
       
        base.OnInitialized();
   }     
    private async Task HandleValidSumit()
    {
       
        Console.WriteLine("Saving...");
        Console.WriteLine(person.FirstName);
        Console.WriteLine(Person.Surname);
    }

   
    // Note: The OnFieldChanged event is raised for each field in the 
     // model
    private void EditContext_OnFieldChanged(object sender, 
            FieldChangedEventArgs e)
    {
        Console.WriteLine(e.FieldIdentifier.FieldName);

    }
    
}

Note: Calling the StateHasChanged() method from event handlers for UI events such as Click, Change, etc. is superfluous. It is automatically called by the framework.

like image 152
enet Avatar answered Apr 23 '26 22:04

enet


You must use EditContext instead of Model in your EditForm. Sample:

<EditForm EditContext="PersonContext" OnValidSubmit="@OnSubmitValidateForm">
    <div class="form-group">
        <label>First Name</label>
        <input type="text" @bind-value="person.FirstName" />
    </div>
    <div class="form-group">
        <label>Surname</label>
        <input type="text" @bind-value="person.Surname" />
    </div>
    <input type="submit" class="btn btn-primary" value="Save" />
</EditForm>

@code {
    EditContext PersonContext;
    Person person = new Person();

    protected override void OnParametersSet()
    {
        PersonContext = new(person);
    }

    void OnSubmitValidateForm()
    {
        if (PersonContext.IsModified())
        {
            //you logic
        }
    }
}
like image 33
Sandro Stadler Avatar answered Apr 23 '26 23:04

Sandro Stadler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!