AutoComplete unable to bind to ID while filtering Text workaround bug

So, after researching through the forums and trying to implement my own solution to the AutoComplete limitation on filtering text while binding to a non-string field, I've tried to work my own solution by encapsulating the AutoComplete control inside another control while marshalling the id/string fields. The problem is that there is still a binding error I cannot get around.

Here is the code for the CustomAutoComplete control:

@using Syncfusion.Blazor.DropDowns
TItem="ModelType"
DataSource="@Items"
@bind-Value="@SelectedItem">



@code {
[Parameter] public Guid? SelectedItemId { get; set; }
[Parameter] public EventCallback SelectedItemIdChanged { get; set; }

ModelType SelectedItem { get; set; }

public class ModelType
{
public Guid Id { get; set; }
public string Name { get; set; }
public override string ToString() => Name;
}

static List Items { get; set; } = new()
{
new ModelType() { Id = new Guid("2ebeb2bb-1f40-4266-9ba5-d3164d0525a6"), Name = "Root Item" },
new ModelType() { Id = Guid.NewGuid(), Name = "Item 1" },
new ModelType() { Id = Guid.NewGuid(), Name = "Item 2" },
new ModelType() { Id = Guid.NewGuid(), Name = "Item 3" }
};

protected override void OnParametersSet()
=> SelectedItem = SelectedItemId.HasValue
? Items.SingleOrDefault(d => d.Id == SelectedItemId)
: null;


Task OnValueChange(ChangeEventArgs args)
=> SelectedItemIdChanged.InvokeAsync(SelectedItem?.Id);
}

Here is the code for another page that implements it:

@page "/"
Index

@SelectedItemId

@code {
Guid? SelectedItemId { get; set; }// = new Guid("2ebeb2bb-1f40-4266-9ba5-d3164d0525a6");
}

What you will notice is that the SelectedItemId that is bound and sent to the CustomAutoComplete control is null. When the value is null, everything works out fine when the user selects an auto-completion item. However, if you uncomment the above statement and initialize the SelectedItemId to a valid guid and restart the application, you will run into a Json exception when the autocompletion control tries to bind. It has to do with the OnParametersSet method finding and initializing the SelectedItem using the initial SelectedItemId.


Here is the exception stack:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: 'R' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
System.Text.Json.JsonException: 'R' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
 ---> System.Text.Json.JsonReaderException: 'R' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
   at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first)
   at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
   at System.Text.Json.Utf8JsonReader.Read()
   at ......

3 Replies

VJ Vinitha Jeyakumar Syncfusion Team April 19, 2022 09:53 AM UTC

Hi Jeff,


We have tried to reproduce the reported issue from our end. but unfortunately, we didn't face any exceptions. While checking the code you have shared, we found that the AutoCompleteFieldSettings of the AutoComplete control was not mentioned, and it is necessary to bind the value fields to the control.

Here, we have created a sample using the code you have shared and modified as per your requirement. Please check the code below,

Code snippet:
SfAutoComplete  TItem="ModelType" TValue="ModelType"
                DataSource="@Items"
                @bind-Value="@SelectedItem">
            <AutoCompleteFieldSettings Value="Id"></AutoCompleteFieldSettings></SfAutoComplete>
             


If still issue persists, at your end can you please modify the attached sample with issue reproducing code.

Regards,
Vinitha


JV Jeff Voigt April 19, 2022 12:45 PM UTC

I am sorry about that. The top of the first code block should read the following:

<SfAutoComplete TValue="ModelType"
                TItem="ModelType"
                DataSource="@Items"
                Value="@SelectedItem"
                ShowClearButton="true"
                ShowPopupButton="true"
                Highlight="true">
    <AutoCompleteFieldSettings Value="Name" />
    <AutoCompleteEvents TValue="ModelType" TItem="ModelType" ValueChange="@OnValueChange" />
</SfAutoComplete>

I cannot adjust the Value to "Id" as then the filtering would happen on the Id rather than the Text field. The whole point is to filter on Name while returning back to the originating control (outside page) the Id. Please use my code block above to replicate the issue. I've also tried going down the custom OnFilter event but that slows the application down tremendously. Please go back and work through my original problem. Thanks!


Here is the code block for the calling page, as that was also messed up on the original submission:

@page "/"
<PageTitle>Index</PageTitle>
<CustomAutoComplete @bind-SelectedItemId="@SelectedItemId" />
<div>@SelectedItemId</div>

@code {
    Guid? SelectedItemId { get; set; } = new Guid("2ebeb2bb-1f40-4266-9ba5-d3164d0525a6");
}


VJ Vinitha Jeyakumar Syncfusion Team April 22, 2022 02:01 PM UTC

Hi Jeff,


If you want to filter using the Name field, you can use the custom filtering options which will also avoid the reported issue. please check the code below,

Code snippet:
<SfAutoComplete TValue="ModelType"
@ref="autoObj"
                TItem="ModelType"
                DataSource="@Items"
                @bind-Value="@SelectedItem"
                ShowClearButton="true"
                ShowPopupButton="true"
               
                Highlight="true">
    <AutoCompleteFieldSettings Value="ID" Text="Name"/>
    <AutoCompleteEvents TValue="ModelType" TItem="ModelType" ValueChange="@OnValueChange" Filtering="OnFilter"/>
</SfAutoComplete>    
             
   
@code {
    
    private async Task OnFilter(FilteringEventArgs args)
    {
        args.PreventDefaultAction = true;
        var query = new Query().Where(new WhereFilter() { Field = "Name", Operator = "startswith", value = args.Text, IgnoreCase = true });

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

        await autoObj.FilterAsync(Items, query);
    }

 }


Regards,
Vinitha

Loader.
Up arrow icon