You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor EditForm创建子数据:返回后表单数据丢失求助

解决方案:Blazor任务表单跳转后数据丢失及内嵌客户创建的实现

一、解决跳转后任务数据丢失的问题

跳转至客户表单后,原任务组件会被销毁,返回时重新初始化,导致数据丢失。以下是两种可靠的解决方式:

1. 利用浏览器本地存储临时保存数据

通过LocalStorage在跳转前序列化存储当前任务数据,返回时反序列化恢复:

@inject Blazored.LocalStorage.ILocalStorageService LocalStorage
@inject NavigationManager NavManager

<EditForm Model="@CurrentTask" OnValidSubmit="@SaveTask">
    <InputLabel>任务标题</InputLabel>
    <InputText @bind-Value="CurrentTask.Title" class="form-control" />

    <InputLabel>搜索客户</InputLabel>
    <InputText @bind-Value="SearchKeyword" class="form-control" />
    <button @onclick="@NavigateToCreateCustomer" class="btn btn-link">客户不存在?去创建</button>

    <button type="submit" class="btn btn-primary mt-3">保存任务</button>
</EditForm>

@code {
    private TaskModel CurrentTask { get; set; } = new();
    private string SearchKeyword { get; set; }

    protected override async Task OnInitializedAsync()
    {
        // 返回时读取临时存储的任务数据
        var savedTaskJson = await LocalStorage.GetItemAsync<string>("TempPendingTask");
        if (!string.IsNullOrEmpty(savedTaskJson))
        {
            CurrentTask = JsonSerializer.Deserialize<TaskModel>(savedTaskJson);
            // 读取后清理存储,避免重复加载
            await LocalStorage.RemoveItemAsync("TempPendingTask");
        }
    }

    private async Task NavigateToCreateCustomer()
    {
        // 跳转前序列化保存当前任务数据
        var taskJson = JsonSerializer.Serialize(CurrentTask);
        await LocalStorage.SetItemAsync("TempPendingTask", taskJson);
        NavManager.NavigateTo("/customers/create");
    }

    private async Task SaveTask()
    {
        // 调用API保存任务
        await TaskService.SaveTaskAsync(CurrentTask);
        // 清理临时存储
        await LocalStorage.RemoveItemAsync("TempPendingTask");
        NavManager.NavigateTo("/tasks");
    }
}

客户表单保存后直接返回任务创建页即可:

private async Task SaveCustomer()
{
    await CustomerService.SaveCustomerAsync(CurrentCustomer);
    NavManager.NavigateTo("/tasks/create");
}

2. 使用全局状态服务暂存数据

创建一个Scoped状态服务,在组件间共享未完成的任务数据:

// 全局状态服务
public class PendingTaskState
{
    public TaskModel UnfinishedTask { get; set; }
}

// Program.cs中注册为Scoped服务
builder.Services.AddScoped<PendingTaskState>();

在任务表单中注入并使用:

@inject PendingTaskState TaskState
@inject NavigationManager NavManager

<EditForm Model="@CurrentTask" OnValidSubmit="@SaveTask">
    <!-- 表单内容同前 -->
</EditForm>

@code {
    private TaskModel CurrentTask { get; set; }

    protected override void OnInitialized()
    {
        // 恢复暂存的任务数据
        if (TaskState.UnfinishedTask != null)
        {
            CurrentTask = TaskState.UnfinishedTask;
            TaskState.UnfinishedTask = null; // 清空状态,避免重复加载
        }
        else
        {
            CurrentTask = new TaskModel();
        }
    }

    private void NavigateToCreateCustomer()
    {
        // 暂存当前任务
        TaskState.UnfinishedTask = CurrentTask;
        NavManager.NavigateTo("/customers/create");
    }

    private async Task SaveTask()
    {
        await TaskService.SaveTaskAsync(CurrentTask);
        NavManager.NavigateTo("/tasks");
    }
}

二、直接在任务表单内录入客户详情的实现

完全支持内嵌客户创建功能,推荐两种方式:

1. 内嵌客户创建组件

创建独立的CustomerCreateComponent,在任务表单中按需显示:

// 任务表单组件
<EditForm Model="@CurrentTask" OnValidSubmit="@SaveTask">
    <!-- 任务字段 -->
    <InputText @bind-Value="CurrentTask.Title" />

    <div class="mt-3">
        <InputText @bind-Value="SearchKeyword" placeholder="搜索客户" />
        <button @onclick="@(() => ShowCustomerForm = !ShowCustomerForm)" class="btn btn-sm btn-secondary ms-2">
            @(ShowCustomerForm ? "收起创建表单" : "客户不存在?直接创建")
        </button>
    </div>

    <!-- 内嵌客户创建组件 -->
    @if (ShowCustomerForm)
    {
        <CustomerCreateComponent OnCustomerSaved="@HandleCustomerCreated" />
    }

    <button type="submit" class="btn btn-primary mt-3">保存任务</button>
</EditForm>

@code {
    private bool ShowCustomerForm { get; set; }
    private TaskModel CurrentTask { get; set; } = new();
    private string SearchKeyword { get; set; }

    private void HandleCustomerCreated(CustomerModel newCustomer)
    {
        // 将新建客户ID关联到任务
        CurrentTask.CustomerId = newCustomer.Id;
        ShowCustomerForm = false;
    }
}

客户创建组件代码:

[Parameter]
public EventCallback<CustomerModel> OnCustomerSaved { get; set; }

private CustomerModel CurrentCustomer { get; set; } = new();

private async Task SaveCustomer()
{
    var savedCustomer = await CustomerService.SaveCustomerAsync(CurrentCustomer);
    await OnCustomerSaved.InvokeAsync(savedCustomer);
}

2. 使用联合模型同时编辑任务和客户

定义包含任务与客户的联合模型,在同一个表单中完成两者的录入:

<EditForm Model="@TaskWithCustomer" OnValidSubmit="@SaveTaskAndCustomer">
    <h5>任务信息</h5>
    <InputText @bind-Value="TaskWithCustomer.Task.Title" class="form-control mb-2" />

    <h5 class="mt-3">客户信息</h5>
    <InputText @bind-Value="TaskWithCustomer.Customer.Name" class="form-control mb-2" />
    <InputText @bind-Value="TaskWithCustomer.Customer.Email" class="form-control mb-2" />

    <button type="submit" class="btn btn-primary mt-3">保存任务及客户</button>
</EditForm>

@code {
    private TaskWithCustomerModel TaskWithCustomer { get; set; } = new();

    private async Task SaveTaskAndCustomer()
    {
        // 先保存客户
        var savedCustomer = await CustomerService.SaveCustomerAsync(TaskWithCustomer.Customer);
        // 关联客户ID到任务
        TaskWithCustomer.Task.CustomerId = savedCustomer.Id;
        // 保存任务
        await TaskService.SaveTaskAsync(TaskWithCustomer.Task);
        NavManager.NavigateTo("/tasks");
    }

    // 联合模型定义
    public class TaskWithCustomerModel
    {
        public TaskModel Task { get; set; } = new();
        public CustomerModel Customer { get; set; } = new();
    }
}

内容的提问来源于stack exchange,提问作者Tala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:57:14