Search code examples
c#listdata-bindingblazor

Blazor @Onchanged / @bind for List item


I want to do a DbUpdate for a List item every time a checkbox is ticked. My List is the property but it does not fire the SET when a @bind in the foreach is changed. I also cannot use @Bind on the foreach and use an @Onchanged at the same time. How could i achieve my goal and what is the best blazor practice?

Foreach: First checkbox handles the method but the passed object is not changed by the "Checked" The second checkbox changes the bool of the object but i can't use @Onchange in combination with @Bind

@foreach (var configuration in dashboardConfigurations)
            {
                <tr>
                    <td>@configuration.Customer.Name</td>
                    <td>@configuration.Customer.Vat</td>
                    <td><input type="checkbox" @onchange="@(async () => await SaveConfiguration(configuration))" checked="@configuration.UploadPurchaseInvoices"/></td> 
                    <td><input type="checkbox" @bind="configuration.UploadSalesInvoices" /></td>
                    <td><button @onclick="@(()=> TestMethod(1))">Disable Customer</button></td>
                </tr>
            }

For: Hoped that a change of the textbox would call the SET of my parameter List but is does nothing...

@for(int i = 0; i < DashboardConfigurations.Count; i++){
                <tr>
                    <td>@DashboardConfigurations[i].Customer.Name</td>
                    <td>@DashboardConfigurations[i].Customer.Vat</td>
                    <td><input type="checkbox" @bind="DashboardConfigurations[i].UploadPurchaseInvoices"/></td>
                    <td><input type="checkbox" @bind="DashboardConfigurations[i].UploadSalesInvoices" /></td>
                    <td><button @onclick="@(()=> TestMethod(1))">Disable Customer</button></td>
                </tr>
            }

Code:

@code { 

    private List<CustomerDashboardConfiguration> dashboardConfigurations;
    [Parameter]
    public List<CustomerDashboardConfiguration> DashboardConfigurations
    {
        get { return dashboardConfigurations; }
        set { dashboardConfigurations = value; }
    }

    internal async Task SaveConfiguration(CustomerDashboardConfiguration customerDashboardConfiguration)
    {
        Console.WriteLine("Saving object");
    }
}

Edit: This works and is exactly what i am trying to achieve but it is pretty ugly in my foreach:

<td><input type="checkbox" @onchange="@(async e =>{configuration.UploadPurchaseInvoices = (bool)e.Value;  await SaveConfiguration(configuration);})" checked="@configuration.UploadPurchaseInvoices"/></td>

Solution

  • Brian has answered the first part of your question.

    This works and is exactly what i am trying to achieve but it is pretty ugly in my foreach.

    <td><input type="checkbox" @onchange="@(async e =>{configuration.UploadPurchaseInvoices = (bool)e.Value;  await SaveConfiguration(configuration);})" checked="@configuration.UploadPurchaseInvoices"/></td>
    

    Sure is! Move the anonymous method into the code section and just call the method.

    <td>
       <input 
          type="checkbox" 
          @onchange="(e) => CheckboxChanged(configuration, e)" 
          checked="@configuration.UploadPurchaseInvoices"
       />
    </td>
    
    @code {
    //....
    async Task CheckboxChanged(DashboardConfiguration configuration, ChangeEventArgs e) 
       {
          configuration.UploadPurchaseInvoices = (bool)e.Value;
          await SaveConfiguration(configuration);
       }
    }
    

    Wish there was a way to use the bound object so the (bool)e.Value isn't needed anymore but this works to!

    There is. See the code below. But there is a problem on event timing that the code illustrates.

    @page "/counter"
    
    <div>
        <input type="checkbox" @bind-value=Checked @oninput=Changed /> CheckBox
    </div>
    
    <div class="bg-dark text-white p-2 m-2">
        Checked : @Checked
    </div>
    
    <div class="alert alert-secondary m-2">
        Message : @message
    </div>
    
    @code {
        private bool Checked { get; set; }
        private string message = string.Empty;
    
        private void Changed( ChangeEventArgs e )
        {
            message = $"Clicked at {DateTime.Now.ToLongTimeString()}. Sumitted Value is {e.Value?.ToString()}  Checked Property was {Checked}.";
        }
    }
    

    enter image description here