Reputation: 73
In the //this works
, the item.isSelected
is updated but the set
in private List<CheckboxModel> checkboxes
won't run. And in the //this causes infinite loop in this component
, nothing is updated and the foreach
loop keeps running infinitely.
@foreach (var item in checkboxes)
{
//this works
@*<div class="checkbox" @key="item">
<input type="checkbox" id="@item.text" @bind="item.isSelected">
<label for="@item.text">@item.text</label>
</div>*@
Console.WriteLine(item.text);
//this causes infinite loop in this component
<Checkbox id="@item.text" @key="item" label="@item.text" @bind-isSelected="item.isSelected" />
}
private List<CheckboxModel> _checkboxes { get; set; } = new List<CheckboxModel>();
private List<CheckboxModel> checkboxes
{
get => _checkboxes;
set
{
// won't run
_checkboxes = value;
Console.WriteLine(string.Join(',', value.Where(x => x.isSelected).Select(x => x.text)));
}
}
This is CheckboxModel.cs
public class CheckboxModel
{
public bool isSelected { get; set; }
public string text { get; set; }
}
Checkbox.razor
<div class="checkbox">
<input type="checkbox" id="@id" @bind="@isSelected">
<label for="@id">@label</label>
</div>
@code {
[Parameter]
public string id { get; set; }
[Parameter]
public string label { get; set; }
private bool _isSelected { get; set; }
[Parameter]
public bool isSelected
{
get => _isSelected;
set
{
isSelectedChanged.InvokeAsync(value);
}
}
[Parameter]
public EventCallback<bool> isSelectedChanged { get; set; }
}
Upvotes: 0
Views: 2156
Reputation: 73
What I end up doing was changing Checkbox.razor
to
CheckboxList.razor
@foreach (var item in items)
{
<div class="checkbox" @key="item">
<input type="checkbox" id="@item.text" checked="@item.isSelected" @onchange="args=> checkedChanged(item,args)">
<label for="@item.text">@item.text</label>
</div>
}
@code {
[Parameter]
public List<CheckboxModel> items { get; set; }
[Parameter]
public EventCallback<List<CheckboxModel>> itemsChanged { get; set; }
async Task checkedChanged(CheckboxModel item, ChangeEventArgs args)
{
item.isSelected = (bool)args.Value;
await itemsChanged.InvokeAsync(items);
}
}
and in the parent file
<CheckboxList @bind-items="checkboxes" />
@code {
private List<CheckboxModel> checkboxes { get; set; }
}
You can find 2 links in here. One of them is simpler and the other one has a select all button
In short: I let the child component handle the logic of looping and handling the List passed into it. The child component passes the List back instead of just a bool which fixes the problem where it doesn't trigger the setter function when I update an item in a List.
Upvotes: 2