首页 > 解决方案 > 具有扩展功能的 EditForm,无需编写 html 部分

问题描述

当存在未保存的更改时,我希望EditForm它会通知我。

在此处输入图像描述

使用事件处理程序(EditContext工作演示)很容易完成:EditContext.OnFieldChanged

    
 <EditForm EditContext="@editContext" OnValidSubmit="()=> isUnsavedChangePresent=false">
   <span>@(isUnsavedChangePresent?"changes are not saved!": "changes are saved")</span>
    <InputText @bind-Value="product.Name" />
    <button >Save it </button>
    <div>(state is updated after focus change)</div>
 </EditForm>

@code {
    private EditContext editContext;
    Product product= new Product();
   bool isUnsavedChangePresent;
    private async void EditContext_OnFieldChanged(object? sender,FieldChangedEventArgs e)
    {
      isUnsavedChangePresent = true;
    }
    class Product
    {
     public string Name {get;set;}
    }

     protected override  void OnParametersSet()
    {
      editContext = new EditContext(product);
      editContext.OnFieldChanged += EditContext_OnFieldChanged;
    }
}

我想把它EditForm作为自己的组件,所以我尝试了这个:

@using Microsoft.AspNetCore.Components.Forms
@inherits EditForm
@ChildContent(EditContext) @*is this correct?? It throws error about cascading parameters*@
@code
{

    protected override async Task OnParametersSetAsync()
    {
        this.EditContext = new EditContext(this.Model);
        EditContext.OnFieldChanged += EditContext_OnFieldChanged;
    }

    private async void EditContext_OnFieldChanged(object? sender, FieldChangedEventArgs e)
    {
        Console.WriteLine("In On Filed Changed");
    }

}

我想使用来自 parent 的 HTML 部分EditForm,但我不知道如何或是否有可能..

标签: blazor

解决方案


以下代码描述了如何定义派生自 EditForm 组件的泛型类...

ExtendedEditForm.cs(放在 Pages 文件夹中)

public partial class ExtendedEditForm <T> : EditForm
    {
        [Parameter]
        public T MyModel { get; set; }

        protected override void OnInitialized()
        {
            EditContext = new EditContext(MyModel);
            EditContext.OnFieldChanged += EditContext_OnFieldChanged;
           
            base.OnInitialized();
        }


        private void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
        {
            Console.WriteLine(e.FieldIdentifier.FieldName);

        }
    }

用法

@page "/"

<ExtendedEditForm MyModel="product" OnValidSubmit ="OnValidSubmit">
    <span>@(IsSaved ? "changes are saved" : "changes are not saved!" )</span>
    <InputText @bind-Value="product.Name" />
    <button type="submit">Save it </button>
    <div>(state is updated after focus change)</div>
</ExtendedEditForm>
    
@code {
       
    Product product = new Product();

    private bool IsSaved { get; set; }

    private void OnValidSubmit()
    {
        IsSaved = true;
    }

    public class Product
    {
        public string Name { get; set; }
    }
}

注意:目前尚不清楚为什么应该对 EditForm 组件进行子类化。如果需要,您可以这样做,但在您的代码示例的情况下,这是微不足道的。

您应该在 OnInitialized(Async) 方法中创建和初始化您的对象,例如 EditContext,而不是在 OnParametersSet(Async) 方法中。

使用 EditContext.OnFieldChanged 设置 isUnsavedChangePresent 的值是错误的,但在这种情况下它可以工作......假设您的表单中有 10 个字段而不是一个。在任何情况下,您都应该在OnValidSubmit单击“提交”按钮时触发的事件处理程序中执行此操作。您应该在按钮元素上放置一个“提交”按钮(或另外)。

@ChildContent(EditContext) @*is this correct?? It throws error about cascading parameters*@

不,这是不正确的。ChildContent 属性继承自 EditForm,您的派生类不会覆盖呈现 EditForm 的 BuildRenderTree 方法,并在其呈现过程中使用 ChildContent。你什么都不做......在这方面没有代码。请注意,可以通过两种方式覆盖 BuildRenderTree 方法:在代码中,通过覆盖 BuildRenderTree 或通过创建组件的视图部分(Razor 标记和 C#)(.razor)


推荐阅读