Reputation: 185
I am new to MudBlazor and I'm trying to create a feature to add tags to a post using MudBlazor components. I have a form with a TextField and a ChipSet.
I want the TextField to use a mask to only allow valid characters in the input box. I can create a regular expression for this pretty easily. For example, only alphanumeric characters and spaces.
When the tag is complete, I want to hit enter to validate and add it to the ChipSet. I was using OnKeyUp for this, as well as automatically making the text lowercase (might be better for OnKeyDown?).
In the future, autocomplete support would be good, but users can create new tags as well, so I would need them to be able to do that.
Right now my code is
<MudTextField T="string" Label="Tags" Required="false" Mask="@tagMask" @bind-Value="tagInput" Immediate="true" OnKeyUp="HandleTagsOnKeyUp" TextUpdateSuppression="false"/>
<MudChipSet AllClosable="true" OnClose="RemoveTag">
@foreach (var tag in tags)
{
<MudChip Text="@tag"></MudChip>
}
</MudChipSet>
List<string> tags = new List<string>();
string tagInput = "";
public void AddTag(string tag) => tags.Add(tag);
public void RemoveTag(MudChip chip) => tags.Remove(chip.Text);
public IMask tagMask = new RegexMask(@"[A-z0-9 \n]*");
async void HandleTagsOnKeyUp(KeyboardEventArgs args)
{
if (args.Key == "Enter")
{
var trimmedInput = tagInput.Trim().ToLower();
//await Task.Delay(100);
if (trimmedInput.Length > 0 && !tags.Contains(trimmedInput))
AddTag(trimmedInput);
tagInput = "";
StateHasChanged();
}
}
But it seems like the mask works and the ChipSet entry and field clearing (mostly) work individually, but together, they both break. Also, it seems like there is an issue with fast typing just missing/deleting characters.
Any suggestions? Am I going about this the correct way?
Upvotes: 1
Views: 4947
Reputation: 3750
In the future, autocomplete support would be good, but users can create new tags as well, so I would need them to be able to do that.
Since you want to use autocomplete to search for your tags as mentioned in you question and also be able to create new tags in future with regex masking, I created an example where both are present. Hopefully, it is what you were looking for.
Demo: https://try.mudblazor.com/snippet/QamGbvGUxUcYguvt
Example code:
@page "/"
<MudStack Row="true">
<MudTextField @ref="_tagInputField"
T="string"
Label="Create a Tag"
Required="false"
Mask="@tagMask"
@bind-Value="tagInput"
Immediate="true"
TextUpdateSuppression="false"/>
<MudButton Size="Size.Small"
Variant="Variant.Filled"
Color="Color.Primary"
OnClick="AddTag"
Class="mt-4">
Add Tag
</MudButton>
</MudStack>
<br/>
<MudAutocomplete @ref="_autocomplete"
T="string"
Label="Select Tags"
SearchFunc="@SearchFunc"
CoerceText="false"
AdornmentIcon="@Icons.Material.Filled.Search"
AdornmentColor="Color.Primary"
ValueChanged="OnAutocompleteValueChanged"/>
<MudChipSet AllClosable="true" OnClose="Closed">
@foreach (var value in SelectedTags)
{
<MudChip Value="@value" Text="@value"></MudChip>
}
</MudChipSet>
@code {
private MudAutocomplete<string>? _autocomplete;
private MudTextField<string>? _tagInputField;
private readonly HashSet<string> SelectedTags = new();
private readonly HashSet<string> tags = new() {"Python", "Java", "JavaScript", "Ruby", "HTML"};
private string tagInput = "";
private readonly IMask tagMask = new RegexMask(@"^[a-zA-Z0-9_.-]*$");
private async Task<IEnumerable<string>> SearchFunc(string value)
{
if (string.IsNullOrEmpty(value))
return tags;
return tags.Where(x => x.Contains(value, StringComparison.InvariantCultureIgnoreCase));
}
private void AddTag()
{
if (!string.IsNullOrEmpty(tagInput))
tags.Add(tagInput);
_tagInputField?.Clear();
}
private void Closed(MudChip chip)
{
SelectedTags.Remove((string)chip.Value);
}
private void OnAutocompleteValueChanged(string? tag)
{
_autocomplete?.Clear();
if (string.IsNullOrEmpty(tag) ||
SelectedTags.Any(x => x == tag))
return;
SelectedTags.Add(tag);
}
}
Upvotes: 2