I am using the TelerikAutoComplete component in Blazor with a custom OnRead function to fetch items from a data source. The issue I am facing is:
When I type in the search box,
OnReadexecutes as expected.But when I erase the search text (set it back to
nullor empty string), theOnReadfunction is not triggered.
My expectation is that when the input is cleared, OnRead should fire again so that I can refresh the data (or return an empty dataset).
<TelerikAutoComplete @ref="@autoCompleteRef"
TItem="@AutoCompleteLookupItem"
Id="@Id"
OnRead="@ReadItems"
DebounceDelay="@DebounceTimeMs"
Filterable="@true"
Placeholder="@Placeholder"
FilterOperator="@FilterOperator"
ValueField="@(nameof(AutoCompleteLookupItem.SelectedValue))"
Value="@Value"
ValueExpression="@( () => Value )"
OnChange="HandleValueConfirmation"
ValueChanged="@HandleValueChanged"
Enabled="IsEnabled"
Class="@Class"
OnBlur="@OnFocusLoose">
<ItemTemplate>
@if (!string.IsNullOrWhiteSpace(@context.SelectedValue))
{
@if (context.Hints == null || !context.Hints.Any())
{
//If we do not have any hints. Display only values
@if (context.Value.Key == "--")
{
//Do not display label. Only display value
<span id="value">@context.SelectedValue</span>
}
else
{
//Display both label and value
<span id="label-and-value">@context.Value.Key: @context.SelectedValue</span>
}
}
else if (context.Hints.Count == 1)
{
//If we only have single hint. Display value along with hint.
<span id="value-with-hint">
<strong>@context.SelectedValue</strong>
@if (!string.IsNullOrWhiteSpace(@context.Hints.First().Value))
{
<i> @context.Hints.First().Value</i>
}
</span>
}
else if (context.Hints.Count == 2)
{
@if (string.IsNullOrWhiteSpace(this.Value) || !LookupBehavior.HasFlag(LookupBehavior.HighlightUserInput))
{
<span id="has-empty-value">
<span id="first-hint">@context.Hints.ElementAt(0).Key: @context.Hints.ElementAt(0).Value<br /></span>
<span id="selected-value">@context.Value.Key: @context.SelectedValue <br /></span>
<span id="second-hint">@context.Hints.ElementAt(1).Key: @context.Hints.ElementAt(1).Value</span>
</span>
}
else
{
<span id="has-value">
<span id="first-hint">@context.Hints.ElementAt(0).Key: @UIUtilities.HighlightUserInputWithBoldTags(HttpUtility.HtmlEncode(@context.Hints.ElementAt(0).Value), HttpUtility.HtmlEncode(this.Value)) <br /></span>
<span id="selected-value">@context.Value.Key: @UIUtilities.HighlightUserInputWithBoldTags(HttpUtility.HtmlEncode(@context.SelectedValue), HttpUtility.HtmlEncode(this.Value)) <br /></span>
<span id="second-hint">@context.Hints.ElementAt(1).Key: @UIUtilities.HighlightUserInputWithBoldTags(HttpUtility.HtmlEncode(@context.Hints.ElementAt(1).Value), HttpUtility.HtmlEncode(this.Value))</span>
</span>
}
}
}
</ItemTemplate>
</TelerikAutoComplete>
<div class="icons">
@if (IsEnabled)
{
<span>
<a id="search-link" @onclick="@OpenAutoComplete" title="search">
<svg class="icon" aria-hidden="true" focusable="false">
<use xlink:href="icons/ece-sprite.svg#ece-icon-search"></use>
</svg>
</a>
</span>
}
else
{
<span class="disable-links">
<a id="search-disabled-link">
<svg class="icon" aria-hidden="true" focusable="false">
<use xlink:href="icons/ece-sprite.svg#ece-icon-search"></use>
</svg>
</a>
</span>
}
</div>
</div>
@if (ShowRequiredMessage && !string.IsNullOrWhiteSpace(RequiredMessage))
{
<span id="required-message" class="k-form-error k-invalid-msg ">
@RequiredMessage
</span>
}
@code {
[Parameter]
public string Id { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public string BoundField { get; set; }
[Parameter]
public EventCallback<string> ValueConfirmed { get; set; }
[Parameter]
public string Value { get; set; }
[Parameter]
public LookupBehavior LookupBehavior { get; set; } = LookupBehavior.None;
[Parameter]
public int DebounceTimeMs { get; set; } = 500;
[Parameter]
public int InitialSkip { get; set; } = 0;
[Parameter] public Func<string, Task<List<AutoCompleteLookupItem>>> FilterMethod { get; set; }
[Parameter]
public StringFilterOperator FilterOperator { get; set; }
[Parameter]
public string? RequiredMessage { get; set; }
[Parameter]
public bool IsEnabled { get; set; } = true;
[Parameter]
public string Class { get; set; }
public bool ShowRequiredMessage { get; set; }
private List<AutoCompleteLookupItem> dataSource;
private TelerikAutoComplete<AutoCompleteLookupItem> autoCompleteRef { get; set; }
private string lastValue;
private bool lostFocus;
async Task ReadItems(AutoCompleteReadEventArgs args)
{
string userInput = string.Empty;
if (args.Request.Filters.Count > 0)
{
Telerik.DataSource.FilterDescriptor filter = args.Request.Filters[0] as Telerik.DataSource.FilterDescriptor;
userInput = filter.Value.ToString();
}
if (lastValue != userInput)
{
if (!lostFocus)
{
lastValue = userInput;
args.Data = await FilterMethod.Invoke(userInput);
}
else
{
lastValue = this.Value;
args.Data = await FilterMethod.Invoke(lastValue);
lostFocus = false;
}
}
}
private void OnFocusLoose() => lostFocus = true;
private async Task HandleValueConfirmation(object userChoice)
{
string currentValue = (string)userChoice;
if (LookupBehavior.HasFlag(LookupBehavior.TriggerActionOnValueConfirmation))
{
if (currentValue != lastValue)
{
await ValueConfirmed.InvokeAsync((currentValue) ?? string.Empty);
lastValue = currentValue;
}
}
if (LookupBehavior.HasFlag(LookupBehavior.ValidateOnValueConfirmation))
{
if (ValueConfirmed.HasDelegate)
ValueConfirmed.InvokeAsync(BoundField);
ShowRequiredMessage = string.IsNullOrEmpty(this.Value) && !string.IsNullOrEmpty(RequiredMessage);
}
await ValueConfirmed.InvokeAsync((currentValue) ?? string.Empty);
}
async Task OpenAutoComplete()
{
await autoCompleteRef.FocusAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
<!--
Below script is used for opening the autocomplete suggestion upon clicking Search Icon
-->
await js.InvokeVoidAsync("TelerikTweaks.attachFocusHandler", autoCompleteRef.Id, ".k-autocomplete");
}
await base.OnAfterRenderAsync(firstRender);
}
private async Task HandleValueChanged(object newValue)
{
this.Value = (string)newValue;
await ValueChanged.InvokeAsync(this.Value);
}
}
Steps to Reproduce:
Type some text in the autocomplete →
OnReadis called ✅.Erase the text so the input becomes empty (
nullor"") →OnReadis not called ❌.
Question:
Is this the expected behavior? If so, how can I force the autocomplete to execute OnRead when the input text is cleared (so I can refresh my dataset)?
Do I need to hook into another event (ValueChanged, OnChange, etc.) to manually call ReadItems in this case?
