How can I get AutoComplete to revert to previous value if user enters an invalid text

Hello,

I can see that sfAutoComplete will clear the text by the user upon tabbing out if that text doesn't match one of the items in the dropdown and AllowCustom="false".

However, if the user has previously selected a valid item from the auto complete dropdown but then returns and enters invalid text, I need the component to revert to the previously selected valid ItemData and corresponding text when the user tabs out of the field .

Furthermore, I need to make sure that the @bind-value property of my model is not updated if the user has entered something invalid.

Please advise how I can achieve this.

Thanks,

Chuck


10 Replies

BC Berly Christopher Syncfusion Team December 14, 2021 03:36 PM UTC

Hi Chuck, 
  
Greetings from Syncfusion support. 
  
When enter the invalid characters in the AutoComplete component, CustomValueSpecifier event will be triggered. So, we can reset the value and passed to args.Item in the event itself. 
  
<SfAutoComplete @ref="AutoObj" TValue="string" TItem="Countries" Placeholder="e.g. Australia" @bind-Value="@AutoVal" AllowCustom="true" DataSource="@Country"> 
    <AutoCompleteFieldSettings Value="Name"></AutoCompleteFieldSettings> 
    <AutoCompleteEvents TValue="string" TItem="Countries" CustomValueSpecifier="OnCustom"></AutoCompleteEvents> 
</SfAutoComplete> 
   public async Task OnCustom(CustomValueSpecifierEventArgs<Countries> args) 
    { 
        args.Item = new Countries() { Name = AutoVal }; 
    } 
 
  
  
Regards, 
Berly B.C 



CR Chuck Richardson December 14, 2021 11:59 PM UTC

Hi Berly,


Thanks for the swift reply and this is exactly what I needed. The CustomValueSpecifier event works perfectly.

This brings me to a related question, I know that I can set the bind-value to the country code when first loading the sfAutoComplete component and it will automatically call ReadAsync when using a custom DataAdaptor (as I am retrieving country names from a back end service) to correctly set the country name in the text box. 

However, is there a way to initialise the sfAutoComplete component with a specific Countries item without having to go through the process of invoking ReadAsync on the DataAdaptor. The reason being that in my case, when generating my model for an existing record, I already know both the country code and country name. So I can create a Countries item from that data and would like to be able to set that Countries item into the sfAutoComplete component when first loaded to avoid the call to the back end service. Only if the user tries to change the text in the sfAutoComplete component should it need to call DataAdaptor.ReadAsync.

Is there a way I can achieve this?

Thanks,

Chuck




BC Berly Christopher Syncfusion Team December 15, 2021 02:45 PM UTC

Hi Chuck Richardson, 
  
If the custom value is assigned to the component, then request will be sent to the server to ensure whether the entered character is available in the data source or not. Due to this, ReadAsync method will be invoked while assigning the custom value to the AutoComplete component. 
  
Regards, 
Berly B.C 



CR Chuck Richardson December 17, 2021 07:50 PM UTC

Hi Berly,


Thanks for the additional info. I guess I can expose a method on the DataAdaptor to set the initial values from my model at the point my component is initialised such the DataAdaptor returns the initial Countries item when ReadAsync is called the first time.


One final question, if the user enters invalid text and presses tab I can set the item back to the valid one using CustomValueSpecifier handler as you have suggested. I also need to display a message to the user and set the focus back to the sfAutoComplete text box in this case. 


I have tried adding the following to the event handler:

await JS.InvokeAsync<object>("alert", "No matching record exists");

await sfCountriesAutoComplete.FocusAsync();


However, focus still moves onto the next control.


Could you please advise how I can set focus back to the  sfAutoComplete text box?


Thanks,


Chuck



DR Deepak Ramakrishnan Syncfusion Team December 20, 2021 06:37 PM UTC

Hi Chuck , 
 
Thanks for the update. 
 
We can achieve your requirement  using keydown event along with blur event . We can detect Tab key in the keyboard event and based on the condition we can call FocusAsync method in blur event as like below highlighted code . 
 
<SfAutoComplete @ref="AutoObj" TValue="string" TItem="Countries" Placeholder="e.g. Australia" @bind-Value="@AutoVal" @onkeydown="@keydownhandler" AllowCustom="true" DataSource="@Country"> 
    <AutoCompleteFieldSettings Value="Name"></AutoCompleteFieldSettings> 
    <AutoCompleteEvents TValue="string" TItem="Countries" Blur="blurhandler" CustomValueSpecifier="OnCustom"></AutoCompleteEvents> 
</SfAutoComplete> 
 
@code { 
    SfAutoComplete<string, Countries> AutoObj; 
 
    public bool isTab { get; set; } 
    public string AutoVal { get; set; } 
    public class Countries 
    { 
        public string Name { get; set; } 
 
        public string Code { get; set; } 
    } 
 
    List<Countries> Country = new List<Countries> 
    { 
        new Countries() { Name = "Australia", Code = "AU" }, 
        new Countries() { Name = "Bermuda", Code = "BM" }, 
        new Countries() { Name = "Canada", Code = "CA" }, 
        new Countries() { Name = "Cameroon", Code = "CM" }, 
        new Countries() { Name = "Denmark", Code = "DK" }, 
        new Countries() { Name = "France", Code = "FR" }, 
        new Countries() { Name = "Finland", Code = "FI" }, 
        new Countries() { Name = "Germany", Code = "DE" }, 
        new Countries() { Name = "Greenland", Code = "GL" }, 
        new Countries() { Name = "Hong Kong", Code = "HK" }, 
        new Countries() { Name = "India", Code = "IN" }, 
        new Countries() { Name = "Italy", Code = "IT" }, 
        new Countries() { Name = "Japan", Code = "JP" }, 
        new Countries() { Name = "Mexico", Code = "MX" }, 
        new Countries() { Name = "Norway", Code = "NO" }, 
        new Countries() { Name = "Poland", Code = "PL" }, 
        new Countries() { Name = "Switzerland", Code = "CH" }, 
        new Countries() { Name = "United Kingdom", Code = "GB" }, 
        new Countries() { Name = "United States", Code = "US" }, 
    }; 
    public async Task OnCustom(CustomValueSpecifierEventArgs<Countries> args) 
    { 
        args.Item = new Countries() { Name = AutoVal }; 
    } 
 
    public void keydownhandler(KeyboardEventArgs args) 
    { 
        if(args.Code == "Tab") 
        { 
            this.isTab = true; 
        } 
    } 
 
    public async Task blurhandler() 
    { 
        if(this.isTab) 
        { 
            await AutoObj.FocusAsync(); 
            this.isTab = false; 
            StateHasChanged(); 
        } 
    } 
} 
 
 
 
 
Thanks, 
Deepak R. 



CR Chuck Richardson replied to Deepak Ramakrishnan December 23, 2021 12:51 AM UTC

Hello,


Thank you for the recommendation on how to set focus back. Before implementing that, our testing has revealed an issue with the original solution to reset to a valid value by implementing CustomValueSpecifier.


This solution works perfectly if you type slow enough but if you enter an invalid value quickly, it doesn't get reverted back to the previous valid value. To reproduce:

  1. Enter "aus" and pick Australia from the popup
  2. Tab out of the control
  3. Select the control and delete Australia from the text box and very quickly enter "o" and tab
Result:
Either the "o" remains in the field or your focus moves to the next control while the popup list is displayed as well.

How would you suggest addressing this?

Thanks,






BC Berly Christopher Syncfusion Team December 23, 2021 02:42 PM UTC

Hi Chuck Richardson, 
  
We would like to inform you that, when clear the value in the AutoComplete component and focus out action will lead to make the component value as null. Since the ValueChange event will be triggered at that time. Due to this, while typing invalid value (“o”) again in the AutoComplete component, the input value goes to null.  
  
Regards, 
Berly B.C 



CR Chuck Richardson December 23, 2021 02:55 PM UTC

Hi Berly,


Thanks for the rapid response. However, I am not entirely clear what the solution is for this issue. Are you saying that the ValueChange event will be fired twice and that I should hook into the second time it is called to restore the original valid value (which I will need to have saved somewhere previously) and set focus back to the control?


Or do I need to implement another approach to preventing the user from leaving the control with an invalid value after rapidly typing a letter and tabbing?


Thanks,


Chuck







BC Berly Christopher Syncfusion Team December 27, 2021 04:00 PM UTC

Hi Chuck, 
  
We will check and update the details in two business days (29th December 2021).  
  
Regards, 
Berly B.C 



BC Berly Christopher Syncfusion Team December 29, 2021 02:38 PM UTC

Hi Chuck, 
  
We would like to inform you that if you are delete the value and focus out the component then ValueChange event will be triggered, and component value will be null. At that time, if you are entering any custom value and tab out the component, then previous value i.e., null value will be updated in the component. This is what we will try to explain the our previous update.  
  
Regards, 
Berly B.C 


Loader.
Up arrow icon