Filter shows "The Request Failed"

When typing in the filter value (ie. where I've typed "blah") - I get a message saying "The Request Failed".


Chrome DevTools doesn't show any failing requests. However, it does seem to be making GET calls to my API as I type (not failing requests though). I don't want it to even try to filter at this point. I have the filter mode set to "On Enter", so I'm not even sure why it's attempting to make these calls anyway.

Any ideas on how to get ride of this annoying "The Request Failed" message?

My filter settings are this:

filterSettings: FilterSettingsModel = {type: 'Menu', mode: 'OnEnter'}

Thanks,
Dan



14 Replies

RR Rajapandi Ravi Syncfusion Team June 1, 2020 12:18 PM UTC

Hi Dan, 

Greetings from syncfusion support 

Based on your query we suspect that you are using remote data and like to filter the value in filter menu autoComplete. The menu filter have autoComplete  component, if you use remotedata you have to handle the filter query at your controller side.  Please refer the below code example and sample for more information.  

Code Snippet:  
OrderController.cs 

public object Get() 
        { 
            var queryString = Request.Query; 
            var data = OrdersDetails.GetAllRecords().ToList(); 
            string sort = queryString["$orderby"];   //sorting      
            string filter = queryString["$filter"]; 
            string auto = queryString["$inlineCount"]; 
             
            if (filter != null) 
            { 
                var newfiltersplits = filter; 
                var filtersplits = newfiltersplits.Split('(', ')', ' '); 
                var filterfield = filtersplits[1]; 
                var filtervalue = filtersplits[3]; 
 
                if(filtersplits.Length == 5) 
                { 
                    if (filtersplits[1] == "tolower") 
                    { 
                        filterfield = filter.Split('(', ')', '\'')[2]; 
                        filtervalue = filter.Split('(', ')', '\'')[4]; 
                    } 
                } 
                if (filtersplits.Length != 5) 
                { 
                    filterfield = filter.Split('(', ')', '\'')[3]; 
                    filtervalue = filter.Split('(', ')', '\'')[5]; 
                } 
                 
                switch (filterfield) 
                { 
 
 
                    case "OrderID": 
 
                        data = (from cust in data 
                                where cust.OrderID.ToString() == filtervalue.ToString() 
                                select cust).ToList(); 
                        break; 
                    case "EmployeeID": 
 
                        data = (from cust in data 
                                where cust.EmployeeID.ToString() == filtervalue.ToString() 
                                select cust).ToList(); 
                        break; 
                    case "Verified": 
 
                        data = (from cust in data 
                                where cust.Verified.ToString() == filtervalue.ToString() 
                                select cust).ToList(); 
                        break; 
 
                    case "CustomerID": 
                        data = (from cust in data 
                                where cust.CustomerID.ToLower().StartsWith(filtervalue.ToString()) 
                                select cust).ToList(); 
                        break; 
                    case "ShipCity": 
                        data = (from cust in data 
                                where cust.ShipCity.ToLower().StartsWith(filtervalue.ToString()) 
                                select cust).ToList(); 
                        break; 
                } 
            } 
 
       } 


Screenshot: 

 


If you still face the same issue, share the complete grid rendering code it will help us to find out the root cause of an issue. 

Regards,
Rajapandi R 



DC Dan Clarke June 2, 2020 06:13 PM UTC

Hi. I think you've misunderstood my question. I don't want to do autocomplete at all. I only want to do the query "on enter", which is the mode I've selected. I don't understand why it's even trying to autocomplete.


RR Rajapandi Ravi Syncfusion Team June 3, 2020 11:57 AM UTC

Hi Dan, 

Sorry for the inconvenience 

From validating your query we found that you are using Filtermenu with mode “OnEnter”. The Filtermenu does not contain “OnEnter” mode. This mode only works for filter bar. We are rendering filtermenu with autocomplete component. This component shows suggestion based on your keypressed. So whenever you pressed the key to start filter the data it sends the post to the server and retrieve the suggestion based on your keypressed it is the default behavior. Please refer the below api link for more information. 


If you like to prevent the query which was sent to the server while keypressed we suggest you to follow the below way to achieve your requirement. 

In this below sample, we are render the textbox for the CustomerID column instead of AutoComplete component. It sends the single post to the server and retrieve the data after you pressed the enter button. Please refer the below code example and sample for more information. 


fetchdata.component.html 
 
<ejs-grid #grid [dataSource]='data' allowFiltering="true" allowPaging="true" [filterSettings]='filterSettings' [editSettings]='editSettings' [toolbar]='toolbar' allowSorting="true" height="320"> 
    <e-columns> 
        .  .  .  .  .  . 
<e-column field='CustomerID' [filter]= 'filter'  headerText='Customer Name' [validationRules]='emailAddRules' width='150'></e-column> 
        .  .  .  .  .  .   
    </e-columns> 
</ejs-grid> 
 

fetchdata.component.ts 
 
export class FetchDataComponent { 
    public data: any; 
    public filter: any; 
    public flValInput: any; 
 @ViewChild('grid') 
  public grid: GridComponent | undefined; 
 
    ngOnInit(): void { 
        this.filterSettings = { type: "Menu"}; 
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true }; 
       this.filter = { 
            ui: { 
                create: (args: { target: Element, Column: Object }) => { 
                    this.flValInput = createElement('input', { className: 'e-input' }); 
                    args.target.appendChild(this.flValInput); 
                }, 
                write: (args: { column: Object, target: Element, parent: any, filteredValue: number | string }) => { 
                    (this.flValInput as any).value = args.filteredValue == undefined ? "" : args.filteredValue; 
 
                }, 
                read: (args: { target: Element, column: any, operator: string, fltrObj: any }) => { 
                    args.fltrObj.filterByColumn(args.column.field, args.operator, (args as any).element.value); 
 
                } 
            }, 
 
 
        }; 
 
    this.data = new DataManager({ 
      url: 'api/Orders', 
      adaptor: new WebApiAdaptor 
    }); 
  } 
 
} 



Regards,
Rajapandi R



DC Dan Clarke June 5, 2020 09:29 AM UTC

Hi. Ah, the documentation wasn't clear that the "OnEnter" wasn't supported by menu filter.

Okay, so I'll get the autocomplete working. My server-side already does that filtering anyway, but you can see I get the error from my screenshot.

I've just looked into this further - and it looks like the error is because I'm using pagination. When using pagination, your grid DataManager (I'm using WebApiAdaptor), expects the API to return data in the following format:

{
  "count": 150,
  "result": [
    {mydata},
    {mydata},
    etc
  ]
}

This is what's breaking the autocomplete. I've just testing hacking my API results to return in the following shape...

[
  {mydata},
  {mydata},
  etc
]

And autocomplete now works. However, my main grid no longer works with pagination enabled.




RR Rajapandi Ravi Syncfusion Team June 8, 2020 12:21 PM UTC

Hi Dan, 

Thanks for the update 

We have analyzed your requirement and while using WebApiAdaptor in data manger we have send skip and take parameter from client side based on the value you can handle the paging at server side. Please refer the below code example and sample for more information. 

 
public object Get() 
        { 
            var queryString = Request.Query; 
            var data = OrdersDetails.GetAllRecords().ToList(); 
            string sort = queryString["$orderby"];   //sorting      
            string filter = queryString["$filter"]; 
            string auto = queryString["$inlineCount"]; 
            if (sort != null) //Sorting 
            { 
                switch (sort) 
                { 
                    case "OrderID": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.OrderID).ToList(); 
                        else 
                            data = data.OrderBy(x => x.OrderID).ToList(); 
                        break; 
                    case "CustomerID": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.CustomerID).ToList(); 
                        else 
                            data = data.OrderBy(x => x.CustomerID).ToList(); 
                        break; 
                    case "ShipCity": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.ShipCity).ToList(); 
                        else 
                            data = data.OrderBy(x => x.ShipCity).ToList(); 
                        break; 
                } 
            } 
            if (filter != null) 
            { 
                var newfiltersplits = filter; 
                var filtersplits = newfiltersplits.Split('(', ')', ' '); 
                var filterfield = filtersplits[1]; 
                var filtervalue = filtersplits[3]; 
 
                if(filtersplits.Length == 5) 
                { 
                    if (filtersplits[1] == "tolower") 
                    { 
                        filterfield = filter.Split('(', ')', '\'')[2]; 
                        filtervalue = filter.Split('(', ')', '\'')[4]; 
                    } 
                } 
                if (filtersplits.Length != 5) 
                { 
                    filterfield = filter.Split('(', ')', '\'')[3]; 
                    filtervalue = filter.Split('(', ')', '\'')[5]; 
                } 
                 
                switch (filterfield) 
                { 
 
 
                    case "OrderID": 
 
                        data = (from cust in data 
                                where cust.OrderID.ToString() == filtervalue.ToString() 
                                select cust).ToList(); 
                        break; 
                    case "EmployeeID": 
 
                        data = (from cust in data 
                                where cust.EmployeeID.ToString() == filtervalue.ToString() 
                                select cust).ToList(); 
                        break; 
                    case "Verified": 
 
                        data = (from cust in data 
                                where cust.Verified.ToString() == filtervalue.ToString() 
                                select cust).ToList(); 
                        break; 
 
                    case "CustomerID": 
                        data = (from cust in data 
                                where cust.CustomerID.ToLower().StartsWith(filtervalue.ToString()) 
                                select cust).ToList(); 
                        break; 
                    case "ShipCity": 
                        data = (from cust in data 
                                where cust.ShipCity.ToLower().StartsWith(filtervalue.ToString()) 
                                select cust).ToList(); 
                        break; 
                } 
            } 
 
            int skip = Convert.ToInt32(queryString["$skip"]);   //Handle pagination here 
            int take = Convert.ToInt32(queryString["$top"]); 
            if (auto ==null) 
            { 
                return new { Items = data}; 
            } 
            else 
            { 
                return take != 0 ? new { Items = data.Skip(skip).Take(take).ToList(), Count = data.Count() } : new { Items = data, Count = data.Count() }; 
            } 
        } 


In WebApi The response object should contain properties Items and Count whose values are a collection of entities and the total count of the entities respectively. Please refer the below documentation for more information. 

The sample response object should look like below. 

{ 
    Items: [{..}, {..}, {..}, ...], 
    Count: 830 
} 
 


Regards,
Rajapandi R



DC Dan Clarke June 10, 2020 06:20 AM UTC

Yep, this confused me too. I'm returning "count" and "result" array (as shown in my last post). I wasn't sure if you'd misunderstood my question - as I'm already returning count/result, and this works perfectly for my grid and paginates. But it does break the filter autocomplete. The autocomplete seems to just expect a flat array of items.


RA rafael.sanchez.costa June 10, 2020 06:27 AM UTC

Hi, first of all: thanks for this Grid, is really really good and I am really happy with it.
Now, please don't take bad, but I think that the documentation and examples is a bit confusing.
For example, I have the same error than "Dan Clarke". 

I am using remote server data app (nodejs+mongo+express) and client app in ANGULAR to build my MEAN application.
I have configured the grid with WebApiAdaptor (is the only one that I am able to run correctly with the documentation examples)

Here in your solution you say that server need to return the result with ITEM array, but this does not work for me. From my server I am returning a JSON with "count" and "result" array, and the grid runs no problem, I have the data, I have pagination, filtering (in remote side), etc. But I am having the same error described here. When I try to use the filter with autocomplete I have an error but when I press intro, the filter work correctly.

I have checked my network (google chrome utils) and I am not returning errors from server, I am returning the same json that works correctly with the grid.

This is the reason becouse I say that the documentation and examples are confusing. How is possible that here I read that I need to use "items" in json result when this does not work (for me) but it works for "result"?

Thanks in advance!

A bit of my code:

   this.data = new DataManager({
      url: 'http://localhost:8080/api/fichas',
      adaptor: new WebApiAdaptor (), 
      crossDomain: true
    });   
    this.filterOptions = {type: 'Menu'};
...
Call from grid in autocomplete:

localhost:8080/api/fichas/?$top=20&$filter=startswith(tolower(apellidos),'r')

Server response:

{
    "count": 2,
    "result": [
        {
            "codigo": 7,
            "nombre": "Ana",
            "apellidos": "Ramos",
            "id": "5edaeab124d645a9a3626de9"
        },
        {
            "codigo": 10,
            "nombre": "Julia",
            "apellidos": "Román",
            "activo": true,
            "createdAt": "2020-06-09T19:49:05.335Z",
            "updatedAt": "2020-06-09T19:49:17.870Z",
            "id": "5edfe7b12dd646a9a46d69a8"
        }
    ]
}



From my grid I get this :



Sorry for the answer in spanish. In english: "The request failed"




RA rafael.sanchez.costa June 11, 2020 03:28 PM UTC

The post from Don where says "The autocomplete seems to just expect a flat array of items." have helped me. So. i have fixed this problem returning 2 diferent formats: one "normal" and another for "inline filter", as showed in the next code (i am using mongoose with express):

          Ficha.find(Filternull, { skip: querySkiplimit: queryLimit }).sort(queryOrderBy)
          .then(data => {
            var resultArray = data
            if (sanitize(req.query.$inlinecount))
              res.send({ count: count , result : resultArray});
            else
              res.send(resultArray);
          })


DC Dan Clarke June 12, 2020 09:22 AM UTC

Thanks Rafael - using the $inlinecount query string argument to determine the shape of the returned data worked for me too.




RR Rajapandi Ravi Syncfusion Team June 15, 2020 12:08 PM UTC

Hi Rafael/Dan, 

We are gald that your issue has been fixed. 

Please get back to us if you need further assistance. 

Regards, 
Rajapandi R 



DC Dan Clarke June 15, 2020 12:12 PM UTC

Hi. It's not fixed - Rafael and myself have worked around the issue - but it's not ideal.

The auto-complete request should ideally support response data.in the paginated format.


RR Rajapandi Ravi Syncfusion Team June 17, 2020 04:12 AM UTC

Hi Dan, 
We have created a new incident under your Direct trac account to follow up with this query. We suggest you to follow up with the incident for further updates. Please log in using the below link.  
Regards, 
Rajapandi R 



PM Paul McDonald June 30, 2021 09:17 PM UTC

Hello, has this issue been resolved in a public release? I have the same issue as both Rafael and Dan, but I am unable to use the workaround that they have used.

My grid is complex and allows for filtering of different types, sorting and paging both on parent and child grids which use the DataManagerRequest object to process the different requests server side.

Due to the complexity, I'm unable to determine if the request for data is due to a filtering event, a sorting event or a paging event, therefor I'm unable to return the data in a different format only if the call was made by an auto-complete filter call.


Thanks,

Paul



SK Sujith Kumar Rajkumar Syncfusion Team July 2, 2021 11:39 AM UTC

Hi Paul, 
 
Greetings from Syncfusion support. 
 
We would like to let you know that by default when Web API adaptor is bound, the Grid expects response data in the format of ‘result’ and  ‘count’. But the auto complete rendered in the Grid filter dialog needs the response returned directly without the count since it has to show all the data related to the typed text. This is its default behavior. 
 
You can differentiate the Grid request from the auto complete request by using the ‘$inlineCount’ property in the server request which will be returned as ‘null’ for the auto complete. So you can resolve this problem by returning the response as demonstrated in the below code snippet, 
 
public object Get()  
        {  
            var queryString = Request.Query;  
            var data = OrdersDetails.GetAllRecords().ToList();  
            string filter = queryString["$filter"];  
            string auto = queryString["$inlineCount"];  
               .  .  .  .  .   
               .  .  .  .  .  
           if (auto ==null)  // This condition will be executed for the auto complete request 
            {  
                return new { Items = data};  
            }  
            else  
            {  
                return take != 0 ? new { Items = data.Skip(skip).Take(take).ToList(), Count = data.Count() } : new { Items = data, Count = data.Count() };  
            }  
}  
 
We have prepared a sample based on this for your reference. You can find it below, 
 
 
Let us know if you have any concerns. 
 
Regards, 
Sujith R 


Loader.
Up arrow icon