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.DropDownsTItem="ModelType"
DataSource="@Items"
@bind-Value="@SelectedItem">
@code {
[Parameter] public Guid? SelectedItemId { get; set; }
[Parameter] public EventCallbackSelectedItemIdChanged { 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 ListItems { 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(ChangeEventArgsargs)
=> 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 ......
| SfAutoComplete TItem="ModelType" TValue="ModelType" DataSource="@Items" @bind-Value="@SelectedItem"> <AutoCompleteFieldSettings Value="Id"></AutoCompleteFieldSettings></SfAutoComplete> |
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");
}
| <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); } } |