问题
When values change in the Form
Component. The Editform does not validate and it does not set the IsModified
of the FieldState
to true. Only on submit it will validate. I see when the values change, the class "Modified" is not added the input tag in HTML. So it looks like the EditContext is not setting the FieldState?
How can I achieve that?
Many thanks!
Code (Simplified):
Form Component
@typeparam TItem
<EditForm EditContext="_editContext" OnValidSubmit="OnValidSumit">
<DataAnnotationsValidator />
<ValidationSummary />
@ChildContent
</EditForm>
@code {
[Parameter] public TItem Model { get; set; }
[Parameter] public EventCallback OnValidSumit { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
private EditContext _editContext;
protected override void OnParametersSet()
{
_editContext = new EditContext(Model);
}
}
PS When I use OnInitialized
instead of OnParametersSet
, I get the modified class. But then there is a problem with the DataAnnotationsValidator
. It's like it's not seeing the value of the EditContext and wil always be valid or invalid on value change (after the frist submit).
protected override void OnInitialized()
{
_editContext = new EditContext(Model);
}
Parent Component
<Form Model="someModel" OnValidSumit="Save">
<InputNumber @bind-Value="Model.Number" />
<InputText @bind-Value="Model.Name" />
<button type="submit">Add</button>
</Form>
@code {
public class SomeModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public SomeModel someModel = new SomeModel();
}
回答1:
Based on what you have posted above and reproducing your problem with the above code, it looks like a couple of things can be adjusted and you'll be working again.
Form.razor
@typeparam TItem
<EditForm EditContext="_editContext" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
@ChildContent
<button type="submit" >Add</button>
<button type="reset" >Reset</button>
</EditForm>
@code {
[Parameter] public TItem Model { get; set; }
[Parameter] public EventCallback<TItem> OnValidSumit { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
private EditContext _editContext;
protected override void OnInitialized()
{
_editContext = new EditContext(Model);
}
async Task HandleValidSubmit()
{
await OnValidSumit.InvokeAsync(Model);
_editContext = new EditContext(Model);
}
}
Key points for the Form component are that I moved the <button>
inside the form so it's no longer supplied as child content. Second, I did use the OnInitialized()
method on startup to initialize the EditContext
.
EDIT Third, the form OnValidSubmit
now calls a private method that invokes the callback, and the callback now takes an argument of TItem
. Once a valid item is submitted, the event callback is awaited, and then the Edit Context is reset.
Fourth, the Form component now has a reset button for a soft reset of the form.
Parent Component
@using System.ComponentModel.DataAnnotations
@* Note the TItem in the line below, specified as the type needed for the EditContext *@
<Form TItem="SomeModel" Model="someModel" OnValidSumit="Save">
<InputNumber @bind-Value="someModel.Id" />
<InputText @bind-Value="someModel.Name" />
</Form>
@code {
public class SomeModel
{
//ID can only be between 1 and 10, for demo purposes
[Range(1,10, ErrorMessage ="ID must be between 1 and 10")]
public int Id { get; set; }
//Name is required and must be only letters
[Required]
[RegularExpression(@"^+[A-Za-z]+$", ErrorMessage ="Name can only contain letters")]
public string Name { get; set; }
}
public SomeModel someModel = new SomeModel();
void Save(SomeModel savedModel)
{
//do something useful with your model info
MethodThatAcceptsSomeModel(savedModel);
// If you want to reset the form, reinitialize the model
someModel = new SomeModel();
}
}
Key points for the Parent component:
I specified the "TItem" value for the Form. I've found that sometimes generic components work without it, but I've solved a lot of Gotchas by adding that in there.
I added the "@using System.ComponentModel.DataAnnotations" line, and then added some Data Annotations decorations to your model properties. The implementation you showed would have only checked for unparseable values, so doing this added some further restrictions to test the validation out. In this setup, the "Name" property will only accept letters and cannot be blank, and the "Id" property will only accept values between 1 and 10.
Lastly, this setup validates when you leave the form field. If you would like to bind to the "input" event rather than the default "change" event, so validation happens as you type, check out this link for the official word from MS on how to extend their input controls.
EDIT per the OP request to reset the form, the
Save
method now takes an argument of typeSomeModel
and can do something with it, and then reinitializes the model property, which will reset the form.
Hope this helps, let me know.
来源:https://stackoverflow.com/questions/61142096/blazor-editcontext-doesnt-trigger-fieldstate