Completed
Last Updated: 30 Oct 2020 15:18 by ADMIN
Release 2.19.0
IT
Created on: 04 Jun 2020 06:47
Category: ComboBox
Type: Bug Report
2
OnChange fires before value binding

When I select an item from the combo box dropdown, the OnChange event fires with the new value, but the model field is not updated yet.

@selectedValue

<TelerikComboBox Data="@myDdlData" TextField="MyTextField" ValueField="MyValueField"
                 @bind-Value="@selectedValue"  OnChange="@MyOnChangeHandler">
</TelerikComboBox>

@code {
    int selectedValue { get; set; }

    IEnumerable<MyDdlModel> myDdlData = Enumerable.Range(1, 20).Select(x => new MyDdlModel { MyTextField = "item " + x, MyValueField = x });
    
    private void MyOnChangeHandler(object theUserInput)
    {
        Console.WriteLine($"COMBO: the models is now {selectedValue} and the handler received {theUserInput}");
    }

    public class MyDdlModel
    {
        public int MyValueField { get; set; }
        public string MyTextField { get; set; }
    }
}

1 comment
ADMIN
Marin Bratanov
Posted on: 08 Jul 2020 16:22

A potential workaround may be keeping a flag with the desired value when setting it (in the example above it is done in OnRead - when a single item exists in the data source) and using that in ValueChanged to update the Value:

 

@SelectedValue
<br />
<TelerikComboBox Data="@Options"
                 OnRead="@ReadItems"
                 Filterable="true"
                 Placeholder="Find what you seek by typing"
                 Value="@SelectedValue"
                 ValueChanged="@( (string v) => MyValueChangeHandler(v) )">
</TelerikComboBox>

@code{
    private void MyValueChangeHandler(string theUserChoice)
    {
        //workaround
        if (theUserChoice == null && TempValue != null)
        {
            SelectedValue = TempValue;
        }
        else
        {
            //this is the typical line mandatory in a ValueChanged handler
            SelectedValue = theUserChoice;
        }
        TempValue = null;
        //end workaround
    }

    public string SelectedValue { get; set; }
    string TempValue { get; set; } // for the workaround
    List<string> Options { get; set; } = new List<string>();

    async Task ReadItems(ComboBoxReadEventArgs args)
    {
        if (args.Request.Filters.Count > 0) // there is user filter input, skips providing data on initialization
        {
            Telerik.DataSource.FilterDescriptor filter = args.Request.Filters[0] as Telerik.DataSource.FilterDescriptor;
            string userInput = filter.Value.ToString();
            string method = filter.Operator.ToString();

            //new data collection comes down from the service
            Options = await GetOptions(userInput, method);

            if (Options.Count == 1)
            {
                //workaround
                TempValue = SelectedValue;
                //end workaround
            }
        }
        else
        {
            Options = new List<string>() { "one", "two", "three" };
        }
    }

    async Task<List<string>> GetOptions(string userInput, string filterOperator)
    {
        await Task.Delay(500); // simulate network delay, remove it for a real app

        List<string> optionsData = new List<string>();
        if (userInput == "a" || userInput == "b")
        {
            optionsData.Add($"single option for input {userInput}");
        }
        else
        {
            for (int i = 0; i < 5; i++)
            {
                optionsData.Add($"option {i} for input {userInput}");
            }
        }

        return optionsData;
    }
}

 

 

Regards,
Marin Bratanov
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.