Roddik
Roddik

Reputation: 45

Is it possible to check/uncheck a checkbox based on other checkboxes state?

I am trying to create a simple lunch scheme webapp, where you can sign up for any business day of the week. I want the user to be able to select each day individually or select a whole week.

What I thought would be a simple method call/check is proving to be seemingly impossible in a Blazor razorpage. I want a checkbox for the whole week, which checks or unchecks all the checkboxes for each individual day. This is pretty straightforward and works as expected. But if I uncheck any of the days, I want the week checkbox to get unchecked as well.

This is what the relevant part of my page looks like:

@foreach (var item in weeks)
{
    <tr>
        <td><input type="checkbox" @onchange="eventArgs => SetAllWeekDays(item.Key, eventArgs.Value)" /> @item.Value.WeekNumber</td>
        <td>
            <input type="checkbox" @bind="item.Value.WeekDays[0].IsSignedUp" />
        </td>
        <td>
            <input type="checkbox" @bind="item.Value.WeekDays[1].IsSignedUp" />
        </td>
        <td>
            <input type="checkbox" @bind="item.Value.WeekDays[2].IsSignedUp" />
        </td>
        <td>
            <input type="checkbox" @bind="item.Value.WeekDays[3].IsSignedUp" />
        </td>
        <td>
            <input type="checkbox" @bind="item.Value.WeekDays[4].IsSignedUp" />
        </td>
    </tr>
}

And this is the SetAllWeekDays method:

private void SetAllWeekDays(int weekNumber, object checkedValue)
{
    if ((bool)checkedValue)
    {
        for (int i = 0; i < weeks[weekNumber].WeekDays.Count; i++)
        {
            weeks[weekNumber].WeekDays[i].IsSignedUp = true;
        }
    }
    else
    {
        for (int i = 0; i < weeks[weekNumber].WeekDays.Count; i++)
        {
            weeks[weekNumber].WeekDays[i].IsSignedUp = false;
        }
    }
}

When I check or uncheck the week, it checks or unchecks all the days, but if I check or uncheck any of the days individually, the checkbox for the week stays unchanged

Checked whole week

Unchecked individual day

I feel like I'm missing some obvious way of databinding a method call to the value of the whole week, as you can't both bind a value and set an @onchange event.

Upvotes: 2

Views: 2630

Answers (1)

enet
enet

Reputation: 45626

Here's a working code sample how to do that... copy and test:

Note that @bind is equivalent to the checked attribute and the @onchange directive, and how I make use of both

@page "/LunchScheme"
@using System;

<table class="table">
    <thead>
        <tr>
            <td>Week</td>
            <td>Monday</td>
            <td>Tuesday</td>
            <td>Wednesday</td>
            <td>Thursday</td>
            <td>Friday</td>
        </tr>
    </thead>
    <tbody>

@foreach(var week in weeks)
{
    <tr>
                <td>
               
    <input type="checkbox" checked="@week.Selected" @onchange="@((args) => { week.Selected = (bool)
            args.Value; Check(week);  } )" />
            </td>

    @foreach(var day in week.DayOfTheWeeks)
    {
        <td>
        <input type="checkbox" checked="@day.Selected" @onchange="@((args) => { day.Selected = (bool)
            args.Value; CheckWeek(week);  } )" />
          </td>
    }
    </tr>

}
 </tbody>
</table>


@code {

    private List<Week> weeks = new List<Week>() { new Week { ID = 1 },
new Week { ID = 2 },
new Week { ID = 3 },
new Week { ID = 4 }};
   
    public class Week
    {
        public int ID { get; set; }
        public bool Selected { get; set; }
        public List<DayOfTheWeek> DayOfTheWeeks { get; set; } = new List<DayOfTheWeek>()
                 { new DayOfTheWeek{ DayOfWeek = DayOfWeek.Monday },
                                 new DayOfTheWeek{ DayOfWeek = DayOfWeek.Tuesday },
                             new DayOfTheWeek{ DayOfWeek = DayOfWeek.Wednesday },
                             new DayOfTheWeek{ DayOfWeek = DayOfWeek.Thursday },
                                  new DayOfTheWeek{ DayOfWeek = DayOfWeek.Friday }};
    }

     public class DayOfTheWeek
    {
        public DayOfWeek DayOfWeek {get; set;}
        public bool Selected {get;set;}

    }

     protected void Check(Week week)
    {
        var toCheck = week.DayOfTheWeeks;
       
        foreach (var day in toCheck)
        {
            day.Selected = week.Selected;
        }

    }

     protected void CheckWeek(Week week)
    {
        var allSelected = week.DayOfTheWeeks.All(day => day.Selected == true);

        if(allSelected)
        {
            week.Selected = true;
        }
       
        else
        {
            week.Selected = false;
        }

    }

}

Upvotes: 3

Related Questions