.netasp.net-coreblazorblazor-server-sideblazor-rendermode

Why won't my button call my function with button type as button?


I am making a website for recipes where users can upload their own recipes. I am struggling with my CreateRecipe page. I want the user to enter an ingredient name, ingredient quantity, and the unit of measure. Then they press the button "Add" which will add their input into my database, and then display their ingredient on the screen. I want to do this dynamically so that the user can add multiple ingredients without the page refreshing and clearing all the other input information. I am having the same problem with the button for "AddIngredient" and "AddInstruction", I can't seem to call the functions with their buttons.

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

Any suggestions?


Solution

  • In the new Blazor Web App project type the default is is static rendering. Your page is not interactive and only a submit button will work.

    For your design you will need to pick another rendermode:

    @page "/create-recipe"
    @rendermode InteractiveServer
    ...