My scenario is that I am trying to save a new Lead
which has property UserId
, but because I have too many leads, I added categories to users, so a user can only have one category.
For this, I created two autocompletes, one for the category and one for users.
The autocomplete for category should set CategoryId
value when selected, CategoryId
should be passed to UserAutcomplete
so that I can filter all users that belong to the given category.
- The problem is that
CategoryAutcomplete
is returning the category name instead of theId
, and therefore I cannot filter the users with the particular category. - Second issue is that the function
ToStringFunc
is supposed to takeFunc<T, string>
, when I try to passint
then it returns error as no overload exists forFunc<int, string>
I have a simple Category and User object:
public class CategoryDto
{
public int Id { get; set; }
public string Name { get; set; }
}
public class UserDto
{
public int Id { get; set; }
public string FullName { get; set; }
public int CategoryId { get; set; }
}
Category autocomplete
public class CategoryAutocomplete : MudAutocomplete<string>
{
private List<CategoryDto>? _categoryList;
[Parameter] public int? CategoryId { get; set; }
[Inject] private ICategoryService ICategoryService { get; set; } = default!;
public CategoryAutocomplete()
{
SearchFunc = SearchNames;
ToStringFunc = ConvertIdToName;
Clearable = true;
ResetValueOnEmptyText = true;
ShowProgressIndicator = true;
MaxItems = 50;
}
protected override async Task OnParametersSetAsync()
{
await LoadCategoryDataAsync();
}
private Task LoadCategoryDataAsync()
{
_categoryList = ICategoryService.DataSource
.Where(x => CategoryId == null || x.Id == CategoryId)
.ToList();
return Task.CompletedTask;
}
private Task<IEnumerable<string>> SearchNames(string value, CancellationToken cancellation)
{
if (_categoryList == null)
return Task.FromResult<IEnumerable<string>>(new List<string>());
var query = _categoryList.AsQueryable();
if (!string.IsNullOrWhiteSpace(value))
{
query = query.Where(x => x.Name!.Contains(value, StringComparison.OrdinalIgnoreCase));
}
var result = query.Select(x => x.Name).Take(MaxItems).ToList();
return Task.FromResult(result.AsEnumerable())!;
}
private string ConvertIdToName(string value)
{
return _categoryList?.FirstOrDefault(x => x.Name!.Contains(value, StringComparison.OrdinalIgnoreCase))?.Name ?? string.Empty;
}
}
User autocomplete:
public class UserAutocomplete : MudAutocomplete<string>
{
private List<UserDto>? _userList;
[Parameter] public string? Id { get; set; }
[Parameter] public int? CategoryId { get; set; }
[Parameter] public string? FullName { get; set; }
[Inject] private IUserService UserService { get; set; } = default!;
public UserAutocomplete()
{
SearchFunc = SearchUsers;
ToStringFunc = ConvertIdToName;
Clearable = true;
ResetValueOnEmptyText = true;
ShowProgressIndicator = true;
MaxItems = 50;
}
protected override async Task OnParametersSetAsync()
{
await LoadUserDataAsync();
}
private Task LoadUserDataAsync()
{
_userList = UserService.DataSource
.Where(x => Id == null || x.Id == Id).ToList();
return Task.CompletedTask;
}
private Task<IEnumerable<string>> SearchUsers(string value, CancellationToken cancellation)
{
if (_userList == null)
{
return Task.FromResult<IEnumerable<string>>(new List<string>());
}
var query = _userList.AsQueryable();
if (!string.IsNullOrWhiteSpace(value))
{
query = query.Where(x => x.FullName
.Contains(value, StringComparison.OrdinalIgnoreCase));
}
if (!string.IsNullOrWhiteSpace(FullName))
{
query = query.Where(x => !x.FullName.Equals(FullName, StringComparison.OrdinalIgnoreCase));
}
var result = query.Select(x => x.Id).Take(MaxItems).ToList();
return Task.FromResult(result.AsEnumerable());
}
private string ConvertIdToName(string id)
{
return _userList?.FirstOrDefault(x => x.Id.Equals(id, StringComparison.OrdinalIgnoreCase))?.FullName ?? string.Empty;
}
}
And I am trying to use both category and user autocomple in a dialog MudDialog
as this:
<MudDialog>
<DialogContent>
<MudForm Model="@Model" @ref="@_form" Validation="@(Validator.ValidateValue(Model))">
<MudGrid Spacing="2">
<MudItem xs="12" sm="4">
<CategoryAutocomplete Label="Pick a Category"
For="@(() => CategoryId)"
@bind-Value="CategoryId">
</CategoryAutocomplete>
</MudItem>
<MudItem xs="12" sm="4">
<UserAutocomplete Label="Pick a User"
For="@(() => Model.UserId)"
FullName="@Model.FullName"
CategoryId="@CategoryId" <--- I want to pass this category id so that I can filter the users that belong to this category
@bind-Value="Model.UserId">
</UserAutocomplete>
</MudItem>
</MudGrid>
</MudForm>
</DialogContent>
<DialogActions>
<MudButton OnClick="Cancel">Cancel</MudButton>
<MudLoadingButton Loading="@_saving" OnClick="Submit">Save</MudLoadingButton>
</DialogActions>
</MudDialog>
@code {
[CascadingParameter] private MudDialogInstance MudDialog { get; set; } = default!;
[EditorRequired][Parameter] public AddEditItemCommand Model { get; set; } = default!;
[Parameter] public Action? Refresh { get; set; }
[Parameter] public string? CategoryId { get; set; }
private MudForm? _form;
}
Any hint or possible solution is greatly apprecaited.