TelerikAutoComplete OnRead not executing when search text is cleared (set to null/empty)

1 Answer 20 Views
AutoComplete
Arjun
Top achievements
Rank 1
Arjun asked on 18 Aug 2025, 09:50 AM

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, OnRead executes as expected.

  • But when I erase the search text (set it back to null or empty string), the OnRead function 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>&nbsp;@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:

  1. Type some text in the autocomplete → OnRead is called ✅.

  2. Erase the text so the input becomes empty (null or "") → OnRead is 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?

1 Answer, 1 is accepted

Sort by
0
Dimo
Telerik team
answered on 18 Aug 2025, 12:16 PM | edited on 18 Aug 2025, 12:17 PM

Hi Arjun,

If I understand the scenario correctly, then my comments are:

  • Firing OnRead event and opening the AutoComplete dropdown are not equivalent behaviors.
  • OnRead fires after the component Value is cleared through its own UI, because this is a change in the filter state.
  • It is expected for the dropdown to close when the Value is cleared. The AutoComplete is effectively a textbox with suggestions, which opens its dropdown after the user types something.
  • It is possible to cancel the OnClose event conditionally in order to leave the dropdown open.
  • In addition, the AutoComplete has Rebind() and Open() methods, which you can use if necessary.

Please review the following example, which shows how you can keep the dropdown open when the user clears the AutoComplete value: https://blazorrepl.telerik.com/GfYWFMlF57rMpwbK55

On a side note, I see that your company has some unassigned licenses and you don't have one. Thus, please ask the license holder to assign licenses to you and all other developers who are working with our products. Currently your account is not entitled to technical support and is not compliant with our license agreement. Thanks.

Regards,
Dimo
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Tags
AutoComplete
Asked by
Arjun
Top achievements
Rank 1
Answers by
Dimo
Telerik team
Share this question
or