Blazor сбрасывает модель в исходное состояние при нажатии кнопки «Отмена» (кнопка «Сброс») в форме редактирования.

У меня есть грубая операция с использованием Blazor Server Side и Editform. Все работает отлично, кроме тех случаев, когда я пытаюсь сбросить форму после редактирования существующей записи.

Когда я что-то меняю в элементе управления формы, а затем нажимаю кнопку сброса, форма закрывается. Данные, которые я изменяю, обновляются в таблице HTML, но не обновляются в базе данных.

Как я могу предотвратить это?

Вот моя модель:

public class Address  
{
    public string province { get; set; }
    public string address { get; set; }
    public string contact_name { get; set; }
    public string phone_number { get; set; }
}

Это моя EditForm:

<EditForm Model="@model" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div class="form-group">
        <InputText @bind-Value="@model.province" />
    </div> 
    <div class="form-group">
        <InputText @bind-Value="@model.contact_name" />
    </div>
    <div class="form-group">
        <InputText @bind-Value="@model.phone_number" />
    </div>
    <div class="form-group">
        <InputText @bind-Value="@model.address" />
    </div>
    <button type="submit" class="btn btn-primary">Save</button>
    <button type="reset" class="btn btn-warning">Cancel</button>
</EditForm>

Вот моя таблица HTML:

@if (address_list== null)
{
    <p>Loading</p>
}
else
{
    <table class="table table-striped text-center">
        <thead>
            <tr>
                <th scope="col" class="text-center">Province</th>
                <th scope="col" class="text-center">Contact Name</th>
                <th scope="col" class="text-center">Phone</th>
                <th scope="col" class="text-center">Address</th>
                <th scope="col" class="text-center">Edit</th>
                <th scope="col" class="text-center">Delete</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var d in  address_list)
            {
                <tr>
                    <td>@d.province</td>
                    <td>@d.contact_person</td>
                    <td>@d.phone_number</td>
                    <td>@d.address</td>
                    <td><button type="button" class="btn btn-link" @onclick="@(() => Edit(d))">Edit</button></td>
                    <td><button type="button" class="btn btn-link" @onclick="@(() => Delete(d))">Delete</button></td>  
                </tr>
            }
        </tbody>
    </table>
}

person Pheakdey Tes    schedule 21.12.2019    source источник


Ответы (2)


Вы не показываете свой серверный код, связанный с формой редактирования, но я предполагаю, что он выглядит примерно так:

@code {
    public Address model { get; set; }
}

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

@code { 

    public Address model {
        get { return _model; }
        set {
            _model = value;
            _clone = new Address {
                province = value.province,
                address = value.address,
                contact_name = value.contact_name,
                phone_number = value.phone_number            
            }
        }
    Address _model;
    Address _clone;

    public void reset () {
        _model.province = _clone.province;
        _model.address = _clone.address;
        _model.contact_name = _clone.contact_name;
        _model.phone_number = _clone.phone_number;
    }

}

Затем в форме редактирования вместо кнопки типа «сбросить» выполните:

<button class="btn btn-warning" @onclick="reset" @onclick:preventDefault>Cancel</button>

Так продлится до тех пор, пока ребята из Microsoft не реализуют что-то вроде:

<InputText @firstNonBlankAsInitial="true" @bind-Value="@model.province" />
person pwilcox    schedule 11.05.2020
comment
Хотя приведенный выше код работает, у меня возникла проблема с передачей события Cancel родительскому компоненту, например для обновления таблицы HTML или закрытия дочерней формы. EventCallback вызывает установщик, перезаписывая _clone. Действие не вызывает StateHasChanged, поэтому ничего не происходит. Вызов StateHasChanged вручную имеет тот же эффект, что и EventCallback. Мой обходной путь - создать копию _clone в родительском компоненте, а не в установщике дочернего. - person flip; 04.04.2021

Легкого решения не может быть, поскольку проблема концептуальна. Вы не можете сбросить форму до начальных значений с помощью сброса типа кнопки. Кнопка «Сброс», сбросит все поля до их начальных значений, то есть до значения, которое они имели при создании HTML-формы.

Однако форма Html может быть уничтожена и создана несколько раз во время одного редактирования из-за автоматического создания Blazor и уничтожения компонентов. Например, если некоторые поля или вся форма находятся в пределах TabItem элемента управления Tab, и / или форма создается / уничтожается всякий раз, когда вы изменяете выбранную вкладку. По этой причине "начальные значения" формы отличаются от начальных значений, появляющихся при первом появлении формы, и являются бессмысленными значениями.

Таким образом, вы не можете воздействовать на поля или формы Html, но вам нужно действовать на модели, которая привязана к форме, поскольку гарантируется, что только базовая модель выдержит все повторные рендеринга Blazor.

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

person Francesco Abbruzzese    schedule 20.04.2020