Reputation: 735
I'm trying to implement new "Virtualize" feature, by creating an scrollable list of checkboxes, where user can search and select multiple items.
Here is my razor code:
@if (this.AllowSearch)
{
<InputTextLined Label="@string.Empty" @bind-Value="@SearchString"/>
}
<Virtualize Items="@displayedItems" Context="item" >
<ItemContent>
<label><input type="checkbox" @bind-value="item.Selected" />@item.DisplayName</label>
</ItemContent>
</Virtualize>
</ul>
Heres my component code:
[Parameter]
public bool AllowSearch { get; set; } = false;
[Parameter]
public string DisplayPropertyName { get; set; }
[Parameter]
public ICollection<T> SourceList { get; set; } = null;
[Parameter]
public Func<T, string, bool> SearchFunc { get; set; }
public string SearchString
{
get => _searchString;
set
{
if (value == _searchString)
return;
_searchString = value;
Search();
}
}
private string _searchString = string.Empty;
protected ICollection<SelectableListItemModel<T>> items;
protected ICollection<SelectableListItemModel<T>> displayedItems;
protected override void OnInitialized()
{
if (SourceList != null)
{
items = SourceList.Select(i => new SelectableListItemModel<T>(i, DisplayPropertyName)).ToList();
displayedItems = items.ToList();
}
}
protected void Search()
{
if (string.IsNullOrWhiteSpace(SearchString) == false)
displayedItems = items.Where(p => SearchFunc(p.Data, SearchString)).ToList();
else
displayedItems = items.ToList();
}
The component renders all the items from sourceList by wraping them in SelectableListItemModel.
public class SelectableListItemModel<T>
{
public bool Selected { get; set; }
public string DisplayName { get; set; }
public T Data { get; private set; }
public SelectableListItemModel(T data, string displayedPropertyName)
{
this.selected = false;
this.Data = data;
if (displayedPropertyName != string.Empty)
this.DisplayName = typeof(T).GetProperty(displayedPropertyName).GetValue(data).ToString();
else
this.DisplayName = data.ToString();
}
}
Now the main issue is with search implementation. But the problem is really hard to explain. Heres picture:
When item is selected and then performed a search, checkboxes are not rerendered, only labels.
Upvotes: 2
Views: 872
Reputation: 3261
I think you should use InputCheckbox
rather than html input
element. The InputCheckBox implemented ValueChanged
to notify the parents. And also use @item.Selected
(with @
at the beginning) instead of item.Selected
because item.selected
is string! :
<EditForm>
<Virtualize Items="@displayedItems" Context="item" >
<ItemContent>
<label><InputCheckbox @bind-value="@item.Selected"></InputCheckbox>@item.DisplayName</label>
</ItemContent>
</Virtualize>
</EditForm>
And
protected aync Task Search()
{
if (string.IsNullOrWhiteSpace(SearchString) == false)
{
displayedItems = items.Where(p => await SearchFunc(p.Data,SearchString)).ToList();
StateHasChanged();
}
else
displayedItems = items.ToList();
}
Upvotes: 1