Blazor EditContext не вызывает FieldState - PullRequest
1 голос
/ 10 апреля 2020

Когда значения изменяются в Form Компоненте. Форма редактирования не проверяется и не устанавливает IsModified из FieldState в значение true. Только после отправки он будет подтвержден. Я вижу, когда значения меняются, класс "Модифицированный" не добавляется тег ввода в HTML. Похоже, что EditContext не устанавливает FieldState?

Как мне этого добиться?

Большое спасибо!

Код (упрощенный):

Компонент формы

@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 Когда я использую OnInitialized вместо OnParametersSet, я получаю модифицированный класс. Но тогда возникает проблема с DataAnnotationsValidator. Как будто он не видит значение EditContext и всегда будет действительным или недействительным при изменении значения (после первой отправки).

protected override void OnInitialized()
{
    _editContext = new EditContext(Model);
}

Родительский компонент

<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 Ответ

1 голос
/ 28 апреля 2020

Исходя из того, что вы опубликовали выше, и воспроизведите вашу проблему с помощью приведенного выше кода, похоже, что несколько вещей можно изменить, и вы снова будете работать.

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);
    }
}

Ключевым моментом для компонента Form является то, что я переместил <button> внутри формы, чтобы он больше не предоставлялся как дочерний контент. Во-вторых, я использовал метод OnInitialized() при запуске, чтобы инициализировать EditContext.

EDIT В-третьих, форма OnValidSubmit теперь вызывает закрытый метод, который вызывает обратный вызов, а обратный вызов теперь принимает аргумент TItem. После того, как верный элемент передан, ожидается обратный вызов события, а затем контекст редактирования сбрасывается.

В-четвертых, компонент Form теперь имеет кнопку сброса для мягкого сброса формы.

Родительский компонент

@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();
    }
}

Ключевые точки для Родительского компонента:

  1. Я указал значение "TItem" для форма. Я обнаружил, что иногда generi c компоненты работают без него, но я решил много Gotchas, добавив это туда.

  2. Я добавил в строке "@using System.ComponentModel.DataAnnotations", а затем добавили некоторые украшения аннотаций данных в свойства модели. Реализация, которую вы показали, проверила бы только непарсируемые значения, поэтому это добавило некоторые дополнительные ограничения для проверки валидации. В этой настройке свойство «Имя» будет принимать только буквы и не может быть пустым, а свойство «Идентификатор» будет принимать значения только от 1 до 10.

  3. Наконец, эта настройка проверяет когда вы покидаете поле формы. Если вы хотите привязать к событию «input», а не к событию «change» по умолчанию, поэтому проверка происходит по мере ввода, проверьте эту ссылку для официального слова от MS о том, как расширить свой ввод управления.

  4. EDIT в соответствии с запросом OP для сброса формы, метод Save теперь принимает аргумент типа SomeModel и может что-то с ним делать, и затем повторно инициализирует свойство модели, что приведет к сбросу формы.

Надеюсь, это поможет, дайте мне знать.

...