diff --git a/samples/BlazorServer/Pages/Index.razor b/samples/BlazorServer/Pages/Index.razor index 83c9312..f94f58d 100644 --- a/samples/BlazorServer/Pages/Index.razor +++ b/samples/BlazorServer/Pages/Index.razor @@ -189,6 +189,23 @@
} +

Blazored Typeahead - Error Handler

+ + + + @person.Firstname + + + @person.Firstname @person.Lastname + + + @context.Message + + +
+ @code { private bool IsDisabled = true; @@ -264,6 +281,16 @@ { return await Task.FromResult(People.Where(x => x.Firstname.ToLower().Contains(searchText.ToLower())).ToList()); } + + private async Task> GetErrorPeople(string searchText) + { + if (searchText.Contains("win", StringComparison.InvariantCultureIgnoreCase)) + { + return await GetPeopleLocal(searchText); + } + + throw new InvalidOperationException("Only people with 'win' in name allowed"); + } private void HandleFormSubmit() { diff --git a/src/Blazored.Typeahead/BlazoredTypeahead.razor b/src/Blazored.Typeahead/BlazoredTypeahead.razor index c6d7350..a1589d9 100644 --- a/src/Blazored.Typeahead/BlazoredTypeahead.razor +++ b/src/Blazored.Typeahead/BlazoredTypeahead.razor @@ -214,4 +214,10 @@ } } + else if (ShowError()) + { +
+ @ErrorTemplate(Error) +
+ } diff --git a/src/Blazored.Typeahead/BlazoredTypeahead.razor.cs b/src/Blazored.Typeahead/BlazoredTypeahead.razor.cs index 623aaf6..2ffacdf 100644 --- a/src/Blazored.Typeahead/BlazoredTypeahead.razor.cs +++ b/src/Blazored.Typeahead/BlazoredTypeahead.razor.cs @@ -43,6 +43,7 @@ public partial class BlazoredTypeahead : ComponentBase, IDisposab [Parameter] public RenderFragment SelectedTemplate { get; set; } [Parameter] public RenderFragment HeaderTemplate { get; set; } [Parameter] public RenderFragment FooterTemplate { get; set; } + [Parameter] public RenderFragment ErrorTemplate { get; set; } [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary AdditionalAttributes { get; set; } [Parameter] public int MinimumLength { get; set; } = 1; @@ -62,6 +63,10 @@ public partial class BlazoredTypeahead : ComponentBase, IDisposab private TItem[] Suggestions { get; set; } = new TItem[0]; private int SelectedIndex { get; set; } private bool ShowHelpTemplate { get; set; } = false; + + private Exception Error { get; set; } + private bool HasError => Error != null; + private string SearchText { get => _searchText; @@ -304,7 +309,6 @@ private async Task ResetControl() await ValuesChanged.InvokeAsync(Values); _editContext?.NotifyFieldChanged(_fieldIdentifier); } - } [JSInvokable("ResetControlBlur")] @@ -332,7 +336,7 @@ private async Task ShowMaximumSuggestions() IsSearching = true; await InvokeAsync(StateHasChanged); - Suggestions = (await SearchMethod?.Invoke(_searchText)).Take(MaximumSuggestions).ToArray(); + Suggestions = await SearchForSuggestionsAsync(); IsSearching = false; await InvokeAsync(StateHasChanged); @@ -386,15 +390,32 @@ private async void Search(Object source, ElapsedEventArgs e) ShowHelpTemplate = false; IsSearching = true; await InvokeAsync(StateHasChanged); - Suggestions = (await SearchMethod?.Invoke(_searchText)).Take(MaximumSuggestions).ToArray(); + Suggestions = await SearchForSuggestionsAsync(); IsSearching = false; - IsShowingSuggestions = true; await HookOutsideClick(); SelectedIndex = 0; await InvokeAsync(StateHasChanged); } + private async Task SearchForSuggestionsAsync() + { + try + { + Error = null; + var suggestions = (await SearchMethod?.Invoke(_searchText)).Take(MaximumSuggestions).ToArray(); + IsShowingSuggestions = true; + + return suggestions; + } + catch (Exception e) when (ErrorTemplate != null) + { + IsShowingSuggestions = false; + Error = e; + return null; + } + } + private async Task HookOutsideClick() { await JSRuntime.OnOutsideClick(_searchInput, this, "ResetControlBlur", true); @@ -403,7 +424,7 @@ private async Task HookOutsideClick() private async Task SelectResult(TItem item) { var value = ConvertMethod(item); - + if (IsMultiselect) { var valueList = Values ?? new List(); @@ -444,14 +465,16 @@ private async Task SelectNotFoundPlaceholder() private bool ShouldShowHelpTemplate() { return SearchText.Length > 0 && - ShowHelpTemplate && - HelpTemplate != null; + ShowHelpTemplate && + HelpTemplate != null; } private bool ShouldShowSuggestions() { return IsShowingSuggestions && - Suggestions.Any() && !IsSearchingOrDebouncing; + Suggestions.Any() && + !IsSearchingOrDebouncing && + !HasError; } private void MoveSelection(int count) @@ -478,11 +501,21 @@ private Task SelectTheFirstAndOnlySuggestion() } private bool IsSearchingOrDebouncing => IsSearching || _debounceTimer.Enabled; + private bool ShowNotFound() { return IsShowingSuggestions && !IsSearchingOrDebouncing && - !Suggestions.Any(); + !Suggestions.Any() && + !HasError; + } + + private bool ShowError() + { + return ErrorTemplate != null && + HasError && + !IsShowingSuggestions && + !IsSearchingOrDebouncing; } public void Dispose() @@ -504,4 +537,4 @@ public async Task Focus() await HandleClickOnMask(); } } -} +} \ No newline at end of file