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

Blazor创建食谱页面Add按钮无法调用函数求助

问题描述

我正在开发一个支持用户上传食谱的网站,当前在CreateRecipe页面遇到问题。我希望用户输入食材名称、数量及计量单位后,点击Add按钮将输入内容存入数据库,并动态在页面上展示该食材,实现无需刷新页面即可添加多种食材的效果。目前AddIngredient和AddInstruction按钮均无法调用对应的函数,相关代码如下:

@page "/create-recipe"
@using CookNet.Data
@inject RecipeService RecipeService
@inject NavigationManager NavigationManager
@using Microsoft.AspNetCore.Components.Forms

<h3>Create Recipe</h3>

<EditForm Model="@Recipe" OnValidSubmit="HandleSubmit" FormName="CreateRecipeForm">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <label>Name:</label>
    <InputText @bind-Value="@Recipe.Name" />

    <label>Description:</label>
    <InputTextArea @bind-Value="@Recipe.Description" />

    <label>Cook Time (minutes):</label>
    <InputNumber @bind-Value="@Recipe.CookTime" />

    <label>Ethnicity:</label>
    <InputText @bind-Value="@Recipe.Ethnicity" />

    <label>Category:</label>
    <InputText @bind-Value="@Recipe.Category" />

    <div class="form-group">
        <label>Ingredient Name:</label>
        <InputText @bind-Value="@NewIngredientName" />
    </div>
    <div class="form-group">
        <label>Quantity:</label>
        <InputNumber @bind-Value="@NewIngredientQuantity" />
    </div>
    <div class="form-group">
        <InputSelect @bind-Value="@NewIngredientQuantityUnit">
            <option value="teaspoon">tsp</option>
            <option value="tablespoon">Tbsp</option>
            <option value="cup">Cup</option>
            <option value="gram">Gram</option>
            <option value="ounce">Ounce</option>
        </InputSelect>
    </div>
    <button type="button" class="btn btn-primary" @onclick="AddIngredientAsync">Add</button>

    <div class="form-group">
        <label>Instructions:</label>
        <InputTextArea @bind-Value="NewInstructionText" />
    </div>
    <button type="button" class="btn btn-primary" @onclick="AddInstructionAsync">Add</button>

    @if (AddedIngredients.Any())
    {
        <h4>Added Ingredients:</h4>
        <ul>
            @foreach (var ingredient in AddedIngredients)
            {
                <li>@($"{ingredient.Quantity} {ingredient.QuantityUnit} - {ingredient.Name}")</li>
            }
        </ul>
    }

    @if (AddedInstructions.Any())
    {
        <h4>Added Instructions:</h4>
        <ul>
            @foreach (var instruction in AddedInstructions)
            {
                int stepNum = 0;
                <li>@($"{stepNum++}. {instruction}")</li>
            }
        </ul>
    }

    <button type="submit" class="btn btn-success">Submit</button>
</EditForm>

@code {
    Recipe Recipe { get; set; } = new Recipe();
    string NewIngredientName { get; set; }
    int NewIngredientQuantity { get; set; }
    string NewIngredientQuantityUnit { get; set; } = "tsp";
    string NewInstructionText { get; set; }
    List<Ingredient> AddedIngredients { get; set; } = new List<Ingredient>();
    List<Instruction> AddedInstructions { get; set; } = new List<Instruction>();

    private async Task AddIngredientAsync()
    {
        Console.WriteLine("BUTTON CLICKED!");
        await RecipeService.AddIngredientToRecipeAsync(Recipe, NewIngredientName, NewIngredientQuantity, NewIngredientQuantityUnit);
        AddedIngredients.Add(new Ingredient
        {
            Name = NewIngredientName,
            Quantity = NewIngredientQuantity,
            QuantityUnit = NewIngredientQuantityUnit
        });
        NewIngredientName = string.Empty;
        NewIngredientQuantity = 0;
        NewIngredientQuantityUnit = "tsp";
    }

    private async Task AddInstructionAsync()
    {
        Console.WriteLine("BUTTON CLICKED!");
        await RecipeService.AddInstructionToRecipeAsync(Recipe, NewInstructionText);
        AddedInstructions.Add(new Instruction
        {
            InstructionText = NewInstructionText
        });
        NewInstructionText = string.Empty;
    }

    async Task HandleSubmit()
    {
        Recipe.DateCreated = DateTime.Now;
        await RecipeService.CreateRecipeAsync(Recipe);
        NavigationManager.NavigateTo("/recipes");
    }
}
解决建议
  • 排查表单验证拦截:虽然按钮是type="button"不会触发表单提交,但EditForm内的DataAnnotationsValidator可能因Recipe模型必填字段未填写,导致组件状态异常阻止事件触发。可临时注释DataAnnotationsValidator和ValidationSummary测试按钮是否正常响应。
  • 强制UI状态更新:Blazor对集合变更的自动检测有限,在AddIngredientAsync和AddInstructionAsync函数末尾添加StateHasChanged();,手动通知UI刷新集合变更。
  • 捕获服务调用异常:在两个Add函数中添加try-catch块,排查RecipeService调用时是否抛出异常,例如:
    private async Task AddIngredientAsync()
    {
        try
        {
            Console.WriteLine("BUTTON CLICKED!");
            await RecipeService.AddIngredientToRecipeAsync(Recipe, NewIngredientName, NewIngredientQuantity, NewIngredientQuantityUnit);
            AddedIngredients.Add(new Ingredient
            {
                Name = NewIngredientName,
                Quantity = NewIngredientQuantity,
                QuantityUnit = NewIngredientQuantityUnit
            });
            NewIngredientName = string.Empty;
            NewIngredientQuantity = 0;
            NewIngredientQuantityUnit = "tsp";
            StateHasChanged();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"添加食材出错: {ex.Message}");
        }
    }
    
  • 检查浏览器控制台:打开F12开发者工具查看是否有Blazor运行时错误,这类错误会直接阻止事件处理函数执行。
  • 修正步骤编号逻辑:当前步骤编号stepNum在循环内定义,每次循环都会重置为0,导致所有步骤显示为0。将stepNum移到循环外:
    @if (AddedInstructions.Any())
    {
        <h4>Added Instructions:</h4>
        <ul>
            int stepNum = 1;
            @foreach (var instruction in AddedInstructions)
            {
                <li>@($"{stepNum++}. {instruction.InstructionText}")</li>
            }
        </ul>
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:25:00