I'm working on a website with a series of checkboxes. Once three are checked, the remaining ones should be disabled. If one of the three previously checked are unchecked, they should all be enabled again.
This is the code I have for the checkboxes:
<input type="checkbox" disabled="@CheckCount" @onchange="Checked"/>
Checked simply tells the parent component that the checkbox in this component changed. The parent component keeps track of this and once three are checked it sets CheckCount to true and passes it to the child component.
How do I factor in the state of the checkbox? Specifically, if a check box is checked I don't want it to ever be disabled. Is there a way to override CheckCount in the child component?
CodePudding user response:
My solution is similar to @Bennyboy who posted first. However, I decided to post anyway since I have a Blazor Fiddle demonstrating how it works. The key is that the logic only disable unchecked items.
Check 3 Items:
<ol>
<li><input type="checkbox" @bind=@Checked[0] disabled=@(!Checked[0] && IsLocked ) /></li>
<li><input type="checkbox" @bind=@Checked[1] disabled=@(!Checked[1] && IsLocked ) /></li>
<li><input type="checkbox" @bind=@Checked[2] disabled=@(!Checked[2] && IsLocked ) /></li>
<li><input type="checkbox" @bind=@Checked[3] disabled=@(!Checked[3] && IsLocked ) /></li>
<li><input type="checkbox" @bind=@Checked[4] disabled=@(!Checked[4] && IsLocked ) /></li>
</ol>
IsLocked: @IsLocked
@code {
bool IsLocked => Checked.Where(p => p).Count() >= 3;
bool[] Checked = new bool[10];
}
CodePudding user response:
The solution to your problem is to disable items if BOTH 1) Count of selected items is 3; 2) the current item is not selected.
The following is a generic approach I often use for that. I create what I call a "carrier" class which is just my display class with a bool
added for selection purposes. Then I can bind to that bool
, and use it in Linq to count or select items:
(https://blazorfiddle.com/s/6vxpmjau)
@foreach (var CI in CheckableItems)
{
<input type="checkbox" @bind="CI.IsSelected"
disabled="@(CheckableItems.Count(ai=>ai.IsSelected) >= 3 && !CI.IsSelected)" />
@CI.Item!.Name <br />
}
You have selected items: @(string.Join(", ", CheckableItems.Where(ai => ai.IsSelected).Select(si=>si.Item.Name))) <br />
Having ID values: @(string.Join(", ", CheckableItems.Where(ai => ai.IsSelected).Select(si=>si.Item.ID.ToString()))) <br/>
Total item count: @(CheckableItems.Count(ai=>ai.IsSelected).ToString())
@code {
public class MyItemClass // Change to whatever class you're selecting from
{
public int ID;
public string? Name;
}
public class CheckableItem // This is the "carrier class."
{
public MyItemClass? Item;
public bool IsSelected;
}
public List<MyItemClass> AllItems = new List<MyItemClass>();
public List<CheckableItem> CheckableItems= new List<CheckableItem>();
protected override void OnInitialized()
{
// Sample data-- can be anything you want to list
AllItems.Add(new MyItemClass { ID = 1, Name = "Moe"});
AllItems.Add(new MyItemClass { ID = 2, Name = "Curly" });
AllItems.Add(new MyItemClass { ID = 3, Name = "Larry" });
AllItems.Add(new MyItemClass { ID = 4, Name = "Mickey" });
AllItems.Add(new MyItemClass { ID = 5, Name = "Minnie" });
AllItems.Add(new MyItemClass { ID = 6, Name = "Donald" });
// Create bool Carrier
foreach (var _item in AllItems) CheckableItems.Add(new CheckableItem { Item = _item });
}
}