Odata autocomplete with multiple fields

Hi, i'm using the autocomplete with an odata endpoint, and I need to a custom filter before send the request to the odata endpoint,

I have the following:

<SfAutoComplete @ref="@autoObj" TValue="string" TItem="GenericAutocompleteResult" cssClass="template" AllowCustom="true"
    Placeholder="Ingrese el valor a buscar"
    Query="@RemoteDataQuery">
    <SfDataManager Headers=@HeaderData Url="@Url" CrossDomain="true" Adaptor="Adaptors.ODataV4Adaptor"></SfDataManager>
    <AutoCompleteTemplates TItem="GenericAutocompleteResult">
        <ItemTemplate>
            <div class="autocomplete-container">
                <div class="autocomplete-container-name">@context.Name </div>
                <div class="autocomplete-container-email">@(context.Email) </div>
            </div>
        </ItemTemplate>
    </AutoCompleteTemplates>
    <AutoCompleteFieldSettings Value="Name"></AutoCompleteFieldSettings>
    <AutoCompleteEvents TItem="GenericAutocompleteResult" OnValueSelect="OnItemSelect" ValueChange="OnItemChange" TValue="string"></AutoCompleteEvents>
</SfAutoComplete>

This implementation works fine and send the filter using the name field, I need to add an OR filter using the same value typed by the user but in this case associated to the email field, so the odata endpoint will look using something like: name like 'something' or email like ''


8 Replies 1 reply marked as answer

DR Deepak Ramakrishnan Syncfusion Team May 16, 2022 03:02 PM UTC

Hi Julito,


Greetings from Syncfusion support.


We are currently working on your requirement , We will update the details in two business days(May 18th, 2022).


Thanks,

Deepak R.





SP Sureshkumar P Syncfusion Team May 18, 2022 06:48 AM UTC

You can achieve your requirement by custom filtering using a filtering events.


Find the code example here:

 

<SfAutoComplete TValue="string" @ref="autoObj" TItem="Country" Placeholder="e.g. Australia" AllowFiltering="true">

    <AutoCompleteFieldSettings Text="Name" Value="Code"></AutoCompleteFieldSettings>

    <AutoCompleteTemplates TItem="Country">

        <ItemTemplate>

            <div class="autocomplete-container">

                <div class="autocomplete-container-name">@context.Name </div>

                <div class="autocomplete-container-email">@(context.Code) </div>

            </div>

        </ItemTemplate>

    </AutoCompleteTemplates>

    <AutoCompleteEvents TValue="string" TItem="Country" Filtering="OnFilter"></AutoCompleteEvents>

</SfAutoComplete>

 

@code {

 

    SfAutoComplete<string, Country> autoObj { get; set; }

    public Query query;

 

    public class Country

    {

        public string Name { get; set; }

 

        public string Code { get; set; }

    }

 

    List<Country> CountryData = new List<Country>

    {

        new Country() { Name = "Australia", Code = "AU" },

        new Country() { Name = "Bermuda", Code = "BM" },

        new Country() { Name = "Canada", Code = "CA" },

        new Country() { Name = "Cameroon", Code = "CM" },

        new Country() { Name = "Denmark", Code = "DK" }

    };

 

    private async Task OnFilter(FilteringEventArgs args)

    {

        args.PreventDefaultAction = true;

 

        WhereFilter nameFilter = new WhereFilter()

            {

                Field = "Name",

                value = args.Text,

                Operator = "startswith",

                IgnoreCase = true

            };

        WhereFilter codeFilter = new WhereFilter()

            {

                Field = "Code",

                value = args.Text,

                Operator = "startswith",

                IgnoreCase = true

            };

        query = new Query().Where(nameFilter.Or(codeFilter));

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

 

        await autoObj.FilterAsync(CountryData, query);

    }

}

To know more about custom filtering. Please refer to the below documentation link: https://blazor.syncfusion.com/documentation/autocomplete/filtering#custom-filtering

We have created the sample and attached the attachment.



Attachment: ServerApp1238326592_e9422971.zip


JA julio Avellaneda May 19, 2022 01:17 PM UTC

Hi all, thanks for the answer, however I have a odata endpoint, and your example uses a local list, how I can use this with the odata endpoint?

await autoObj.FilterAsync(CountryData, query);

the above line uses the CountryData (local data)


Thanks,



SP Sureshkumar P Syncfusion Team May 20, 2022 09:24 AM UTC

You can use the DataSource instead of the local data variable in the FilterAsync method call.

Find the code example here:

private async Task OnFilter(FilteringEventArgs args)

    {

        args.PreventDefaultAction = true;

 

        WhereFilter nameFilter = new WhereFilter()

            {

                Field = "Name",

                value = args.Text,

                Operator = "startswith",

                IgnoreCase = true

            };

        WhereFilter codeFilter = new WhereFilter()

            {

                Field = "Code",

                value = args.Text,

                Operator = "startswith",

                IgnoreCase = true

            };

        query = new Query().Where(nameFilter.Or(codeFilter));

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

        await autoObj.FilterAsync(this.autoObj.DataSource, query);

    }




JA julio Avellaneda May 21, 2022 03:00 PM UTC

Thanks for the answer, now it sends the two filters, but with this I'm getting the following error:

System.TypeInitializationException: The type initializer for 'Microsoft.AspNetCore.OData.Query.Expressions.ExpressionBinderBase' threw an exception. System.InvalidOperationException: Sequence contains more than one matching element


The odata request is: https://localhost:44386/odata/Users?$count=true&$filter=(contains(tolower(Name),%27testing%27))%20or%20(contains(tolower(Email),%27testing%27))&$select=Id,Name,Email&$skip=0&$top=30

The odata configuration is:

services
            .AddOData(opt => opt.AddModel("odata", GetEdmModel())
                .Filter()
                .Count()
                .Select()
                .SetMaxTop(100));

Regards,




SP Sureshkumar P Syncfusion Team May 23, 2022 07:01 AM UTC

We suspect that the sample level multiple queries replicate the reported issue in your application. We suggest you use the predicate to resolve the issue.

Please find the modified filtering code

private async Task OnFilter(FilteringEventArgs args)

    {

        args.PreventDefaultAction = true;

        var Col1Pre = new WhereFilter();

        var predicate = new List<WhereFilter>();

        predicate.Add(new WhereFilter() { Condition = "or", Field = "Name", value = args.Text, Operator = "startswith", IgnoreCase = true });

        predicate.Add(new WhereFilter() { Condition = "or", Field = "Code", value = args.Text, Operator = "startswith", IgnoreCase = true });

        Col1Pre = WhereFilter.Or(predicate);

        var query = new Query().Where(Col1Pre);

        await autoObj.FilterAsync(this.autoObj.DataSource, query);

    }

If you still have faced the same issue, please provide detailed information with the sample to replicate the issue from our end to update an exact solution as early as possible.

Also, please provide mentioned sends the two filters: is $filter query present two times in a single request or request sent two times.


Marked as answer

JA julio Avellaneda May 28, 2022 03:58 PM UTC

Hello, thanks it works.



RP Ranjani Prabakaran Syncfusion Team May 30, 2022 07:17 AM UTC

Thanks for letting us know that the given solution works. Please get back to us if you need any further assistance.


Regards,

Ranjani


Loader.
Up arrow icon