Paul
Paul

Reputation: 705

blazor editform change events

I want to have an InputSelect in a blazor editform that is bound to a model value and also has an onchange event that changes other properties in the model based on the new value.

binding to both @bind-Value and @onchange does not work (im guessing because bind value uses both the value and the value changed properties of the input.

I can bind to oninput, but I would like to know if there is a better way to do this.

<InputSelect id="inputPeriod" name="inputPeriod" class="form-control" @bind-Value="model.Period" @oninput="periodChanged">


protected void periodChanged(ChangeEventArgs e)
        {}

I can bind to oninput like this

but ideally I would like to bind to the @onchange event after the model property has been updated, or know what the best practice is for this. without using the bind-value the model validation will not work so the only alternative way I can think of is to have the change events working inside the properties in my model, but that seems wrong

Upvotes: 3

Views: 16421

Answers (2)

enet
enet

Reputation: 45596

Here's a silly sample in which you have to enter your name, and then select your pet, the result of which is renaming you after your dear pet. The sample describes how you can manipulate your model when a field changes:

<EditForm EditContext="@EditContext">
<DataAnnotationsValidator />

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

</div>
<div class="form-group">
    <label for="body">Select your pet: </label>
    <InputSelect @bind-Value="@person.Pet">
        <option value="Cat">Cat</option>
        <option value="Dog">Dog</option>
        <option value="Horse">Horse</option>
        <option value="Lion">Lion</option>
    </InputSelect>
     <ValidationMessage For="@(() => person.Pet)" />
</div>

<p>
    <button type="submit">Submit</button>
</p>
</EditForm>


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


    protected override void OnInitialized()
    {
        EditContext = new EditContext(person);
        EditContext.OnFieldChanged += EditContext_OnFieldChanged;

        base.OnInitialized();
    }

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

            person.Name = person.Pet;

        }
    }


    public class Person
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Pet { get; set; }
    }
}

the only alternative way I can think of is to have the change events working inside the properties in my model, but that seems wrong

Not at all...

There's no requirement for models to implement INotifyPropertyChanged, but if they do, you can easily wire that up to the EditContext. Then you have no need to use the built-in Input* components - you can instead bind to regular HTML elements and still get modification notifications. This provides more flexibility in how the UI is rendered, at the cost of more complexity and boilerplate in your model classes.

Hope this helps...

Upvotes: 25

LordSilvermort
LordSilvermort

Reputation: 277

This is one solution which achieves what you want without using the two way binding. Instead the value is bound to the selectbox only, which will trigger the validation.

<InputSelect 
    id="inputPeriod" name="inputPeriod"      
    value="model.Period"
    class="form-control" 
    @onchange="periodChanged"
> 



@code
{

    void periodChanged(ChangeEventArgs e) 
        {
            model.Period = (string) e.Value;
            //your logic... 
        }

}

Upvotes: 2

Related Questions