refresh combobox datasource

I see that the datasource refresh functions arent in the combobox object anymore.  how would I refresh the datasource of the combobox now?


I have  combobox that sits in a custom control.  on load it would load default items.  If a parameter is passed to the control, the load function in my control is ran again, (which calls my api), and sets the list item the combobox uses for its data source.  However it does not update currently.


    <SfComboBox TValue="string"
                TItem="Reservation"
                @ref="comboObj"
                ID="ID"
                Placeholder="Select a reservation"
                AllowFiltering="true"
                DataSource="@reservationList"
                IgnoreCase="true"
                IgnoreAccent="true" @bind-Value="Value">

        <ComboBoxTemplates TItem="Reservation">
           </HeaderTemplate>-->
            <ItemTemplate>
                <div class="d-flex flex-row justify-content-between">
                    <div>@((context as Reservation).DocNumber)</div>
                    <div class="text-muted">@((context as Reservation).Customer.Name)</div>
                 </div>
            </ItemTemplate>

            <NoRecordsTemplate>
                No reservation Found.
            </NoRecordsTemplate>

        </ComboBoxTemplates>

        <ComboBoxFieldSettings Text="Name" Value="Id"></ComboBoxFieldSettings>
        <ComboBoxEvents TValue="string" TItem="Reservation" ValueChange="reservationOnChange" Filtering="OnFilter"></ComboBoxEvents>
    </SfComboBox>

@{

public List<Reservation> reservationList { get; set; }
[Parameter] public string CustomerId { get; set; }
[Parameter] public EventCallback<string> CustomerIdChanged { get; set; }

protected override async Task OnInitializedAsync()
    {
          await LoadReservations();
    }

    protected override async Task OnParametersSetAsync()
    {
        using (_log.BeginScope("OnParametersSetAsync"))
        {
            try
            {
                if (CustomerId != null)
                {
                    await LoadReservations(CustomerId);
                }
            }
            catch (Exception ex)
            {
                _log.LogError(500, ex.Message, ex);
            }
        }
    }

    private async Task LoadReservations(string CustomerId = null)
    {
        try
        {
            var reservationClient = newReservationsClient(_Globals._HttpClient_Tenant);
            var plp = await reservationClient.ReservationsGetAsync(_Globals.CurrentAddressbarCompanyID.Value, new List<string>() {CustomerId} );
            reservationList = plp.ToList();
            StateHasChanged();
        }
        catch (Exception ex)
        {


        }

    }




}


7 Replies 1 reply marked as answer

SN Sevvandhi Nagulan Syncfusion Team October 27, 2020 01:55 PM UTC

Hi Rudi, 



Greetings from Syncfusion support. 



We checked the reported requirement. You can refresh the data source by directly affecting the data source variable. Also, We made sample with the provided code snippet and we cannot reproduce the mentioned issue. Here we have attached the ensured sample. Kindly check with the attached sample and provide an issue replicating sample by modifying the below attached sample that will help us to further validate the issue and provide you with a better solution from our end. 


<SfComboBox TValue="string" 
                TItem="Reservation" 
                @ref="comboObj" 
                ID="ID" 
                Placeholder="Select a reservation" 
                AllowFiltering="true" 
                DataSource="@reservationList" 
                IgnoreCase="true" 
                IgnoreAccent="true" @bind-Value="Value"> 
        <ComboBoxTemplates TItem="Reservation"> 
            <ItemTemplate> 
                <div class="d-flex flex-row justify-content-between"> 
                    <div>@((context as Reservation).ID)</div> 
                    <div class="text-muted">@((context as Reservation).Text)</div> 
                </div> 
            </ItemTemplate> 
 
            <NoRecordsTemplate> 
                No reservation Found. 
            </NoRecordsTemplate> 
 
        </ComboBoxTemplates> 
        <ComboBoxFieldSettings Text="Text" Value="ID"></ComboBoxFieldSettings> 
    </SfComboBox> 
 
<button @onclick="Refresh">Change DataSource</button> 
 
public void Refresh() 
    { 
        reservationList = new List<Reservation>() 
        { 
                new Reservation(){ ID= "Game1", Text= "American Football" }, 
                new Reservation(){ ID= "Game2", Text= "Badminton" }, 
                new Reservation(){ ID= "Game3", Text= "Basketball" }, 
                new Reservation(){ ID= "Game4", Text= "Cricket" }, 
        }; 
    } 

Please find the sample below, 





Also, try changing the data source type observable collection to reflect the changes automatically. 


public ObservableCollection<Reservation> reservationList1 { get; set; } 
 
    public class Reservation 
    { 
        public string ID { get; set; } 
        public string Text { get; set; } 
    } 
 
    public void Refresh() 
    { 
        reservationList = new List<Reservation>() 
    { 
                new Reservation(){ ID= "Game1", Text= "American Football" }, 
                new Reservation(){ ID= "Game2", Text= "Badminton" }, 
                new Reservation(){ ID= "Game3", Text= "Basketball" }, 
                new Reservation(){ ID= "Game4", Text= "Cricket" }, 
        }; 
        reservationList1 = new ObservableCollection<Reservation>() 
    { 
                new Reservation(){ ID= "Game1", Text= "American Football" }, 
                new Reservation(){ ID= "Game2", Text= "Badminton" }, 
                new Reservation(){ ID= "Game3", Text= "Basketball" }, 
                new Reservation(){ ID= "Game4", Text= "Cricket" }, 
        }; 
    } 


Regards, 
Sevvandhi N 



Marked as answer

JE Jeremy November 14, 2020 10:42 AM UTC

Hi Sevvandhi,

your sample if very different to the code that HappyCamper prepared.

In your example, the loading of the datasource (reservationsList) is done via a synchronous event driven from the UI.

HappyCamper 's example (and one that I am also struggling with) was done via asynchronous events. It is not possible for use to mody our code to reload the data via the push of a button.

I think it has been mentioned a number of times (in the DataGrid questions) that is seems very difficult to load data asynchronously into a lot of the Syncfusion controls.

Can you please provide a sample where the data is loaded as part of the InitialiseAsync function?




JE Jeremy November 14, 2020 11:09 AM UTC

As a side note, i think there is also an issue that i see using an ObservableCollection - in that every time an item is added it calls events that refresh data on the screen. If I load 100 items into my combobox list (all from an initial database query) that sems a horrible waste of CPU time udpdating the combo box.

I know from experience that controls from other companies have functions "BeginEdit" and "EndEdit" for this purpose - it allows the developer to use an ObservableCollection to manage data in a control, and when the developer knows they are going to load a list of data, they can call ComboBox.BeginEdit which prevents any graphic updates from occuring whilst the datasource is being modified. When finished the developer then calls ComboBox.EndEdit, which performs a refresh of the control to load the current datasource into the combobox list ...

Does Syncfusion have this ability to programmitically prevent UI updates whilst the ObservableCollection is being changed?


TR Trevor replied to HappyCamper November 14, 2020 03:30 PM UTC

I see that the datasource refresh functions arent in the combobox object anymore.  how would I refresh the datasource of the combobox now?


I have  combobox that sits in a custom control.  on load it would load default items.  If a parameter is passed to the control, the load function in my control is ran again, (which calls my api), and sets the list item the combobox uses for its data source.  However it does not update currently.


    <SfComboBox TValue="string"
                TItem="Reservation"
                @ref="comboObj"
                ID="ID"
                Placeholder="Select a reservation"
                AllowFiltering="true"
                DataSource="@reservationList"
                IgnoreCase="true"
                IgnoreAccent="true" @bind-Value="Value">

        <ComboBoxTemplates TItem="Reservation">
           </HeaderTemplate>-->
            <ItemTemplate>
                <div class="d-flex flex-row justify-content-between">
                    <div>@((context as Reservation).DocNumber)</div>
                    <div class="text-muted">@((context as Reservation).Customer.Name)</div>
                 </div>
            </ItemTemplate>

            <NoRecordsTemplate>
                No reservation Found.
            </NoRecordsTemplate>

        </ComboBoxTemplates>

        <ComboBoxFieldSettings Text="Name" Value="Id"></ComboBoxFieldSettings>
        <ComboBoxEvents TValue="string" TItem="Reservation" ValueChange="reservationOnChange" Filtering="OnFilter"></ComboBoxEvents>
    </SfComboBox>

@{

public List<Reservation> reservationList { get; set; }
[Parameter] public string CustomerId { get; set; }
[Parameter] public EventCallback<string> CustomerIdChanged { get; set; }

protected override async Task OnInitializedAsync()
    {
          await LoadReservations();
    }

    protected override async Task OnParametersSetAsync()
    {
        using (_log.BeginScope("OnParametersSetAsync"))
        {
            try
            {
                if (CustomerId != null)
                {
                    await LoadReservations(CustomerId);
                }
            }
            catch (Exception ex)
            {
                _log.LogError(500, ex.Message, ex);
            }
        }
    }

    private async Task LoadReservations(string CustomerId = null)
    {
        try
        {
            var reservationClient = newReservationsClient(_Globals._HttpClient_Tenant);
            var plp = await reservationClient.ReservationsGetAsync(_Globals.CurrentAddressbarCompanyID.Value, new List<string>() {CustomerId} );
            reservationList = plp.ToList();
            StateHasChanged();
        }
        catch (Exception ex)
        {


        }

    }




}


You forgot to call your CustomerID onInitialized


SN Sevvandhi Nagulan Syncfusion Team November 16, 2020 12:45 PM UTC

Hi Jeremy/ Trevor, 
 
 
Thanks for the update. 
 
 
Query 1: 
 
 
Can you please provide a sample where the data is loaded as part of the InitialiseAsync function? 
 
Response: 
 
We prepared the sample by loading the asynchronous data in the InitialiseAsync function. We could not replicate the reported issue. Please find the sample below, 
 
 
Query 2:  
 
I think it has been mentioned a number of times (in the DataGrid questions) that is seems very difficult to load data asynchronously into a lot of the Syncfusion controls. 
 
 
Response: 
 
 
Could you please list out the controls that you are facing issue?. 
 
 
Query  3:  
 
As a side note, i think there is also an issue that i see using an ObservableCollection - in that every time an item is added it calls events that refresh data on the screen. If I load 100 items into my combobox list (all from an initial database query) that sems a horrible waste of CPU time udpdating the combo box. 


 
I know from experience that controls from other companies have functions "BeginEdit" and "EndEdit" for this purpose - it allows the developer to use an ObservableCollection to manage data in a control, and when the developer knows they are going to load a list of data, they can call ComboBox.BeginEdit which prevents any graphic updates from occuring whilst the datasource is being modified. When finished the developer then calls ComboBox.EndEdit, which performs a refresh of the control to load the current datasource into the combobox list ... 
 
 
Response: 
 
We checked the reported requirement. You can add the item to the existing data source using AddItem public method without refreshing the entire data source. You can also insert the item based on the given index. Hence, we suggest to use this method for adding the item. 
 
 
   public void onClick() 
    { 
        var data = new List<Reservation>() { new Reservation() { Text = "Italy", ID = "It" } }; 
        comboObj.AddItem(data,1); 
    } 
 
 
Please find the sample below, 





Regards, 
Sevvandhi N 



HA Hay Abados September 21, 2023 01:18 PM UTC

Here i struggle with a similar issue:

this is the razor component:

@using Syncfusion.Blazor.DropDowns

@using Syncfusion.Blazor.Popups

@using System.Collections.ObjectModel;

@inject ISecurityService SecurityService


 <div >

     <SfTooltip @ref="TooltipObj" ID="Tooltip" Target=".e-list-item .name[title]">

     </SfTooltip>

     <SfComboBox @ref="comboBoxObj" TItem="EmployeeFullDetailsSearch" TValue="string" AllowFiltering="true" DataSource="@EmployeesTry">

         <ComboBoxEvents TItem="EmployeeFullDetailsSearch" TValue="string" OnClose="OnClose" Opened="OnOpen" Filtering="@OnTypingComboBoxAsync" OnValueSelect="@chooseEmployee"></ComboBoxEvents>

         <ComboBoxFieldSettings Text="FullName" Value="FullName"></ComboBoxFieldSettings>

     </SfComboBox>

 </div>

when typing in the combo box I want to bring new items from my DB (total items 200K and I don't want to bring all at once).
but it's not working, I don't see the new results in the comboBox I see "NO RECORDS FOUND" but i can see i have items in my EmployeesTry , and it seems the problem is because of async await cause I tried hard code as your example and it worked but bringing new items from DB don't.
I tried both List and ObservableCollection both didn't work.

I also tried to add a ref to the SfComboBox but it  didn't work also.

@code {

[Parameter]

Participants participant { get; set; }

[Parameter]

public ObservableCollection Employees { get; set; }

[Parameter]

public GridInjector Injector { get; set; }

[Parameter]

public EventCallback> chooseEmployee { get; set; }

[Parameter]

public EventCallback Filteringhandler { get; set; }



public ObservableCollection EmployeesTry { get; set; }

SfTooltip TooltipObj;

 SfComboBox<string, EmployeeFullDetailsSearch> comboBoxObj;

public Boolean isOpen { get; set; } = false;


private bool intelMode;

protected override async Task OnInitializedAsync()

{

EmployeesTry = new ObservableCollection(await SecurityService.GetEmployeeSearch(""));

}

protected override void OnParametersSet()

{

base.OnParametersSet();

Injector.CompanyChanged = CompanyCheck;

CompanyCheck(participant.CompanyName);

}

private void CompanyCheck(string name)

{

intelMode = name == "Intel";

StateHasChanged();

}

public void OnOpen(PopupEventArgs args)

{

isOpen = true;

}

public void OnClose(PopupEventArgs args)

{

TooltipObj.CloseAsync();

}

protected override async Task OnAfterRenderAsync(bool firstRender)

{

if (isOpen)

{

await TooltipObj.RefreshAsync();

}

}


private async Task OnTypingComboBoxAsync(FilteringEventArgs args)

{

    //await GetEmployees(args.Text);


    EmployeesTry.Clear();

    StateHasChanged();

    var result = await SecurityService.GetEmployeeSearch(args.Text);

    foreach (var item in result)

    {

        EmployeesTry.Add(item);

    }

    await comboBoxObj.RefreshDataAsync();

    StateHasChanged();

}



how can I solve this? all I try to do is have a comboBox that filters from a DB.




KP Kokila Poovendran Syncfusion Team September 27, 2023 11:21 AM UTC

Hi HayAbados,


We apologize for any inconvenience caused by the issue you've encountered. We have carefully reviewed your query and have created a sample that addresses your scenario. In this sample, we have prevented the default filtering behavior by using "args.PreventDefaultAction = true;". By doing this, we were able to pass the current typed text value to the "FilterAsync" method along with the query. As a result, the ComboBox now filters values based on your typed input.


Here's the code snippet that demonstrates this:


private ObservableCollection<Country> CountriesFiltered = new ObservableCollection<Country>() {

        new Country() { Name = "France", Code = "FR" },

        new Country() { Name = "Finland", Code = "FI" },

        new Country() { Name = "Germany", Code = "DE" },

        new Country() { Name = "Greenland", Code = "GL" }

};

 

 

private async Task OnFilter(FilteringEventArgs args)

    {

        args.PreventDefaultAction = true;

        var query = new Query().Where(new WhereFilter() { Field = "Name", Operator = "contains", value = args.Text, IgnoreCase = true });

 

        query = !string.IsNullOrEmpty(args.Text) ? query : new Query();

 

        await comboObj.FilterAsync(CountriesFiltered, query);

    }



You can find more details and examples in our documentation under the "Custom Filtering" section: https://blazor.syncfusion.com/documentation/combobox/filtering#custom-filtering


If our solution doesn't fully address your issue or if you have additional questions, please provide us with more details, or feel free to modify the shared sample according to your specific scenario. This will help us validate the problem further and provide you with a more tailored solution.


If you encounter any further difficulties or have any more questions, please reach out to us. We're here to assist you.


Regards,

Kokila Poovendran.



Attachment: BlazorServerProject_44cbfc9a.zip

Loader.
Up arrow icon