When using an EditForm component and changing a Model property all child components get disposed and reinitialized.
@*My custom component*@
<h3>MyCustomComponent</h3>
@code {
protected override void OnInitialized()
{
System.Diagnostics.Debug.WriteLine("My custom component initialized");
}
}
@*End My custom component*@
@*Index page*@
@page "/"
<EditForm Model="ModelData">
<InputText @bind-Value="ModelData.Name"></InputText>
<MyCustomComponent></MyCustomComponent>
<button type="button" @onclick="SaveAndAddNew">Save data and add new entry</button>
</EditForm>
@code {
public MyModel ModelData { get; set; }
protected override void OnInitialized()
{
ModelData = new MyModel();
}
public void SaveAndAddNew()
{
ModelData = new MyModel();
}
public class MyModel
{
public string Name { get; set; }
}
}
When clicking on the button, a new model object is created and all child components are reinitialized.
This is as-designed.
Changing EditForm.Model creates a new EditContext. Your controls are destroyed and recreated because once their EditContext has been set it cannot be altered.
@partyelite thanks for contacting us.
I believe @mrpmorris is right here. I'm closing this issue as the behavior is by design, but @SteveSandersonMS or @pranavkm can chime in if I'm wrong.
You are dismissing this issue too soon.
To answer a comment from the InputBase component
// We don't support changing EditContext because it's messy to be clearing up state and event
// handlers for the previous one, and there's no strong use case. If a strong use case
// emerges, we can consider changing this.
There are many data entry web applications that will be build using blazor and almost every single app has a form for some kind of a data entry. I order to make lives easier for people who enter data we open a form and once the data is entered they can save the current data and start inserting a new one without closing the form (create a new instance of a model like in the example above).
Destroying a child content is not problematic until some of the components within an EditForm have some sort of logic written on initialized (like querying a database, some api call.. etc). That logic is now unnecessarily executed.
@partyelite I've reopened this issue for triage purposes.
I've looked at the code involved and seeing as the EditContext itself is discarded and recreated when the EditForm.Model changes it seems there is no state that will persist.
All people have to do is
public override async Task SetParametersAsync(ParameterView parameters)
{
EditContext previousEditContext = EditContext;
await base.SetParametersAsync(parameters);
if (EditContext != previousEditContext)
{
// Hook up EditContext exactly as you would in OnInitializedAsync
}
}
This is a pattern I am already following anyway. It was immediately obvious, I thought. It made more sense than OnInitialized*().
I'm in favour of this change as it makes more sense - but obviously you need to consider existing users.
Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.
This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!
Most helpful comment
You are dismissing this issue too soon.
To answer a comment from the InputBase component
There are many data entry web applications that will be build using blazor and almost every single app has a form for some kind of a data entry. I order to make lives easier for people who enter data we open a form and once the data is entered they can save the current data and start inserting a new one without closing the form (create a new instance of a model like in the example above).
Destroying a child content is not problematic until some of the components within an EditForm have some sort of logic written on initialized (like querying a database, some api call.. etc). That logic is now unnecessarily executed.