Search code examples
listselectmodelblazordropdown

Blazor bind dropdown selection in a list to model item


I have a list of expenses on a page. Each expense has a dropdown to select the category and subcategory. My category select component has an onchange event so the list of subcategories can change based on the category. The dropdowns themselves work. However, I can't figure out how to bind them to their expense. I think I'm just not understanding some things on this works, specifically EditForm which I think I need but I'm not sure. The answer maybe out there already but I can't seem to get the right combination of things to look for. I've seen examples of how EditForm works with a model (and I think I've written one correctly before) but combining it with the list is what's presenting the challenge.

Here's my applicable front end code:

<EditForm Model="@expenses">
    <table>
        @foreach (Expense expense in expenses)
        {
            <tr>
                <td>@expense.Key</td>
                <td>@expense.Date</td>
                <td>@expense.Item</td>
                <td>@expense.Cost</td>
                <td>
                    <select id="categoryID" value="@expense.Category.Name" @onchange="OnChangeCategory">
                        <option value="0" selected>Choose Category</option>
                        @foreach (Category category in categories)
                        {
                            <option value="@category.Name">@category.Name</option>
                        }
                    </select>
                </td>
                <td>
                    <select id="subCategoryID" bind="@expense.Category.SelectedSubCategory">
                        <option value="0" selected>Choose SubCategory</option>
                        @foreach (string subCategory in subCategories)
                        {
                            <option value="test">@subCategory</option>
                        }
                    </select>
                </td>
                <td>
                </td>
            </tr>
        }
    </table>
    <button @onclick="SaveExpenses">Save Expenses</button>
</EditForm>

Here's the back end code:

@code {
    public List<Expense> expenses = new List<Expense>();

    private void OnChangeCategory(ChangeEventArgs e)
    {
        subCategories = new List<string>();

        foreach (Category category in categories)
        {
            if (category.Name == e.Value.ToString())
            {
                subCategories = category.SubCategories;
            }
        }
    }
}

Like I said, the dropdowns display what they're supposed to but they never get attached to their expense.

Here's a picture of what the page does. Basically just showing two list items and the dropdowns. Shows two expense list items with two columns being working dropdowns

Thanks in advance!


Solution

  • In the OnChange event you can create a delegate event and pass the current expense object as a parameter. On selection change you can assign the selected dropdown value to the expense category object.

    <select id="categoryID" value="@expense.Category.Name" @onchange="(event) => OnChangeCategory(event, expense)">
        <option value="0" selected>Choose Category</option>
        @foreach (Category category in categories)
        {
            <option value="@category.Name">@category.Name</option>
        }
    </select>
    
    private void OnChangeCategory(ChangeEventArgs e, Expense expense)
    {
        // Assign selected category to the expense
        if(expense.Category == null)
        {
            expense.Category = new Category();
        }
        
        expense.Category.Name = e.Value.ToString();
    
    }