New to Telerik UI for Blazor? Download free 30-day trial

Autocomplete - Refresh Data

The most common reason you would use an ObservableCollection is to make a component (like a grid, treeview, treelist, dropdown) change or react when you change that collection.

When you want to refresh the component data source like that, there are two important framework behaviors you need to be aware of - when ObservableCollection instances fire events, and how to refresh the data of a component when it is not an observable collection.

In this article:

Rebind Method

To refresh the AutoComplete data when using OnRead, call the Rebind method of the TelerikAutoComplete reference. This will fire the OnRead event and execute the business logic in the handler.

@* Clicking on the Rebind button will delete the first item from the datasource and refresh the data in the UI *@

@using Telerik.DataSource.Extensions

<TelerikButton OnClick="@RebindAutoComplete">Rebind the AutoComplete</TelerikButton>

<TelerikAutoComplete TItem="@String"
                     @ref="@AutoCompleteRef"
                     OnRead="@ReadItems"
                     @bind-Value="@SelectedValue">
</TelerikAutoComplete>

@code{
    private TelerikAutoComplete<string> AutoCompleteRef { get; set; }

    private void RebindAutoComplete()
    {
        if (Options.Count > 0)
        {
            Options.RemoveAt(0);
        }

        AutoCompleteRef.Rebind();
    }

    public string SelectedValue { get; set; }
    List<string> Options { get; set; } = new List<string>();

    async Task ReadItems(AutoCompleteReadEventArgs args)
    {
        await Task.Delay(1000);
        args.Data = Options.ToDataSourceResult(args.Request).Data;
    }

    protected override async Task OnInitializedAsync()
    {
        Options = new List<string>() { "one", "two", "three" };
    }
}

As part of our 3.0.1 release we introduced the Rebind method to the component reference. This would make the rest of the approaches in this article obsolete.

Observable Data

Databound components can benefit from live data - when the data source collection changes, the components should update to reflect that change. Most data-bound components in the Telerik UI for Blazor suite implement such functionality.

When the Data of the component is a collection that implements the INotifyCollectionChanged interface (such as ObservableCollection), the Telerik components subscribe to its CollectionChanged event to update. This means that adding items, removing items, or clearing the collection updates the components (its .Add(), .Remove() and .Clear() methods).

The Observable collections fire the CollectionChanged event only when their Add, Remove and Clear methods are called. They do not fire it when you change the value of a field of one of their elements.

Observable data is not supported with manual data operations via the OnRead event.

Bind the Autocomplete component to an ObservableCollection, so it can react to collection changes.

@* Add/remove a suggestion to see how the Autocomplete reacts to the change. *@

@using System.Collections.ObjectModel

<h4>Add suggestion</h4>
<TelerikTextBox @bind-Value="@ValuetoAdd"></TelerikTextBox>

<TelerikButton OnClick="@AddSuggestion">Add suggestion</TelerikButton>
<br />

<h4>Remove the last suggestion</h4>
<TelerikButton OnClick="@RemoveSuggestion">Remove the last suggestion</TelerikButton>
<br />

<h4>Autocomplete suggestions: @Suggestions.Count</h4>
<br />

<TelerikAutoComplete Data="@Suggestions" ValueField="@( nameof(SuggestionsModel.Suggestion) )" @bind-Value="@TheValue" />

@code{
    string TheValue { get; set; }

    string ValuetoAdd { get; set; }

    void AddSuggestion()
    {
        if (!string.IsNullOrWhiteSpace(ValuetoAdd))
        {
            Suggestions.Add(
        new SuggestionsModel { Suggestion = ValuetoAdd, SomeOtherField = Suggestions.Count + 1 }
        );
            ValuetoAdd = string.Empty;
        }
    }

    void RemoveSuggestion()
    {
        if (Suggestions.Count > 0)
        {
        Suggestions.RemoveAt(Suggestions.Count - 1);
        }
    }

    ObservableCollection<SuggestionsModel> Suggestions { get; set; } = new ObservableCollection<SuggestionsModel>
    {
        new SuggestionsModel { Suggestion = "first", SomeOtherField = 1 },
        new SuggestionsModel { Suggestion = "second", SomeOtherField = 2 },
        new SuggestionsModel { Suggestion = "third", SomeOtherField = 3 }
    };

    public class SuggestionsModel
    {
        public string Suggestion { get; set; }//the auto complete needs only the string field
        public int SomeOtherField { get; set; }
    }
}

If you need to add/remove many items to/from the collection, consider creating a new collection and provide its reference to the data parameter. Thus, the component will re-render only once (when the data collection reference is changed) instead of re-rendering multiple times in response to the Add/Remove events.

New Collection Reference

In Blazor, the framework will fire the OnParametersSet event of a child component (which is how child components can react to outside changes) only when it can detect a change in the object it receives through the corresponding parameter (like Data for the data sources of Telerik components). This detection works as follows:

  • For primitive types (such as numbers, strings), this happens when their value changes.

  • For complex types (such as data collections like List, or any IEnumerable, and application-specific models/objects), this happens when the object reference changes.

    Thus, you would usually need to create a new reference for the view-model field (such as TreeViewData = new List<MyTreeViewItem>(theUpdatedDataCollection);) when you want the component to update.

Create new collection reference to refresh the Autocomplete data.

@* Add/remove a suggestion to see how the Autocomplete reacts to the change. *@

<h4>Add suggestion</h4>
<TelerikTextBox @bind-Value="@ValuetoAdd"></TelerikTextBox>

<TelerikButton OnClick="@AddSuggestion">Add suggestion</TelerikButton>
<br />

<h4>Remove the last suggestion</h4>
<TelerikButton OnClick="@RemoveSuggestion">Remove the last suggestion</TelerikButton>
<br />

<h4>Load new collection</h4>
<TelerikButton OnClick="@LoadNewData">Load data</TelerikButton>
<br />

<h4>Autocomplete suggestions: @Suggestions.Count</h4>
<br />

<TelerikAutoComplete Data="@Suggestions" ValueField="@( nameof(SuggestionsModel.Suggestion) )" @bind-Value="@TheValue" />

@code{
    string TheValue { get; set; }

    string ValuetoAdd { get; set; }

    void AddSuggestion()
    {
        if (!string.IsNullOrWhiteSpace(ValuetoAdd))
        {
            Suggestions.Add(
        new SuggestionsModel { Suggestion = ValuetoAdd, SomeOtherField = Suggestions.Count + 1 }
        );
            Suggestions = new List<SuggestionsModel>(Suggestions);
            ValuetoAdd = string.Empty;
        }
    }

    void RemoveSuggestion()
    {
        if (Suggestions.Count > 0)
        {
            Suggestions.RemoveAt(Suggestions.Count - 1);
            Suggestions = new List<SuggestionsModel>(Suggestions);
        }
    }

    void LoadNewData()
    {
        var newData = new List<SuggestionsModel>
        {
        new SuggestionsModel { Suggestion = "fourth", SomeOtherField = 4 },
        new SuggestionsModel { Suggestion = "fifth", SomeOtherField = 5 },
        new SuggestionsModel { Suggestion = "sixth", SomeOtherField = 6 }
        };

        Suggestions = new List<SuggestionsModel>(newData);

        Console.WriteLine("New data collection loaded.");
    }

    List<SuggestionsModel> Suggestions { get; set; } = new List<SuggestionsModel>
    {
        new SuggestionsModel { Suggestion = "first", SomeOtherField = 1 },
        new SuggestionsModel { Suggestion = "second", SomeOtherField = 2 },
        new SuggestionsModel { Suggestion = "third", SomeOtherField = 3 }
    };

    public class SuggestionsModel
    {
        public string Suggestion { get; set; }//the auto complete needs only the string field
        public int SomeOtherField { get; set; }
    }
}

See Also

In this article