How to prevent loading of datasource before filter

Hello

I have a DropDownList with a lots of items (> 10000). I'd like to use server filtering, but when I click on the drop down button, the list is populated with the full set of items.

My DropDownList is as follows:

@(Html.EJ().DropDownList("Product_Id")
        .WatermarkText("Search for product")
        .DropDownListFields(df => df.Value("Id").Text("Name"))
        .Datasource(Model.GetProductsDataSource())
        .EnableFilterSearch(true)
        .EnableIncrementalSearch(false)
        .EnableServerFiltering(true)       
        .LoadOnDemand(true)
 )

I tried to prevent loading of a list in my controller action, like this:

public ActionResult ProductsDataSource(DataManager dataManager)
{
    if (dataManager.Where == null || dataManager.Where.Count == 0)
    {
        return new JsonResult
        {
            Data = new object[0], //  new[] { new { Id = "", Name= "" } },
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    }
    else
    {
// perform database query
    }
}

which works, but if I don't select any item in the drop down list, it stops working. Think works if I use the commented code, but in this case I have an empty item in the list.
So, is it possible to prevent calling the datasource if there's no search/filter string?

Thanks, Tom

9 Replies

KR Keerthana Rajendran Syncfusion Team April 12, 2018 04:04 PM UTC

Hi Tomislav, 
 
We checked your query and prepared a sample based on our understanding. We suggest you to use itemsCount property of DropDownList along with allowVirtualScrolling  set to true so that items will be loaded based on items count and the remaining items will be loaded only on scrolling. You can set itemsCount which has to be loaded during initial DropDownList click and server filtering will be done with the entire dataSource on search. Please refer to the below given code and UG 
 
@Html.EJ().DropDownList("Products_id").Datasource(ds => ds.URL("http://js.syncfusion.com/demos/ejServices/Wcf/Northwind.svc/")).Query("ej.Query().from('Customers').take(50)").DropDownListFields(f => f.Value("CustomerID").Text("CustomerID")).EnableServerFiltering(true).EnableFilterSearch(true).EnableIncrementalSearch(true).LoadOnDemand(true).AllowVirtualScrolling(true).ItemsCount(10) 
 
 
If we have misunderstand , kindly revert with clear details on your requirement so that we can proceed further. 
 
Regards, 
Keerthana. 



TT Tomislav Tustonic April 12, 2018 07:20 PM UTC

Hello
I tried your suggestion, but it doesn't work. My DropDownList looks like:
@(Html.EJ().DropDownList("Product_Id")
        .WatermarkText("Search for product")
        .DropDownListFields(df => df.Value("Id").Text("Name"))
            .EnableServerFiltering(true)
            .EnableFilterSearch(true)
            .EnableIncrementalSearch(false)  // tried both true and false
            .LoadOnDemand(true)
            .AllowVirtualScrolling(true)
            .ItemsCount(2)
 )
When I click on the dropdown button, I receive first two items, but when I search, dropdownlist remains empty.

My initial request and response are:
Req:
{"select":["Name","Id"],"requiresCounts":true,"take":2}
Resp:
{"result":[{"Id":"00000000-0000-0000-0000-000000000020","Name":"EXCALIBUR"}, {"Id":"00000000-0000-0000-0000-000000000001","Name":"Product 01"}],"count":20}
When I start typing the filter string, I receive multiple responses, like this:
Req:
{"take":2,"where":[{"isComplex":false,"field":"Name","operator":"contains","value":"Prod","ignoreCase":true,"anyCondition":""}]}
Resp:
{"result":[{"Id":"00000000-0000-0000-0000-000000000001","Naziv":"Product 01"},{"Id":"00000000-0000-0000-0000-000000000002","Naziv":"Product 02"}],"count":14}
which means that the server side works ok and the results are being returned to the client.

I also tried your exact code, calling Northwind demo service. Your query string returns 50 items to the dropdownlist, and then takes 10 from the returned set. When I remove take(50) from the query, then it correctly returns top 10.
However, after I receive initial set of 10 and start typing the filter string, I receive this error response:
{"error":{"code":"","message":{"lang":"en-US","value":"Query options $select, $expand, $filter, $orderby, $inlinecount, $skip, $skiptoken and $top are not supported by this request method or cannot be applied to the requested resource."}}}

It seems that the virtual scrolling is broken and only works if I don't filter anything.
Perhaps the problem is in the JSON response or something...


KR Keerthana Rajendran Syncfusion Team April 13, 2018 11:29 AM UTC

Hi Tomislav,    
   
Sorry for the inconvenience.   
   
We couldn’t predict how data is bound to DropDownList since the dataSource property and controller code is missing in the provided code snippet. We have prepared a sample for your reference by modifying the previously given code. As your requirement, to load only two items, you can remove the query property and directly provide the exact Url and ItemsCount as shown below.   
   
@Html.EJ().DropDownList("Product").Datasource(ds => ds.URL("https://js.syncfusion.com/demos/ejServices/Wcf/Northwind.svc/Customers")).DropDownListFields(f => f.Value("CustomerID").Text("CustomerID")).EnableServerFiltering(true).EnableFilterSearch(true).EnableIncrementalSearch(true).LoadOnDemand(true).AllowVirtualScrolling(true).ItemsCount(2)   
   
Two items will be loaded as shown below on initial click   
   
    
   
During filter the matched items will be added to the list as shown below   
   
   
   
Please download the sample from the following link.  
   
   
Please add the Url for binding dataSource as done in the above sample and if issue persists, kindly modify the above sample else share us code snippet of both View and Controller page, so that we can proceed further.   
   
Regards,                                                                        
Keerthana.   
  
 



TT Tomislav Tustonic April 14, 2018 05:37 PM UTC

Hello
Thanks for the response. I have tried your example, but it doesn't work. I have installed the following packages from the Syncfusion nuget source:
  • Syncfusion.AspNet.Mvc5 - 16.1.0.32
  • Syncfusion.JavaScript - 16.1.0.32
  • Syncfusion.Web.Base45 - 16.1.0.32
  • Syncfusion.Web.FileFormatsBase45- 16.1.0.32

Here are the screenshots:

Initially the list is empty:

After typing the filter string I get the error:

I have created a sample similar to what I'm using in my application. I tried with two different JSON outputs. Here are the screenshots:

The first output has the same result as your example, empty list and error:


The second JSON output initially gives the list with some results:

But filtering doesn't give any result:


Attachment: ItemsCount1262146408__Copy_ae3fdc11.zip


KR Keerthana Rajendran Syncfusion Team April 16, 2018 01:04 PM UTC

Hi Tomislav, 
 
Query: After typing the filter string I get the error: 
 
You receive this error because search is done on empty DropDownList. Please bind the dataSource before performing search. 
 
Query: But filtering doesn't give any result: 
 
We have checked the provided sample and the issue occurs because of the list type result and count returned as shown below 
 
 
Whereas in the previous sample, list is returned as shown in the below image. 
 
 
So we suggest you to pass the JsonResult which returns the data as shown in the above format so that filtering will work fine in the sample. 
 
Regards, 
Keerthana. 
 



TT Tomislav Tustonic April 16, 2018 03:02 PM UTC

Hello
I still can't make it work.

I think that the view for my second example needs a following modification:
.Datasource(ds => ds.URL("/DropDownList/CustomersDataSource2").Adaptor(AdaptorType.UrlAdaptor))
otherwise the DataManager parameter in the CustomersDataSource2 has no values the properties like search, take etc.

Would you, please, modify my example in a way that satisfies following requirements:
  1. Initial loading of a datasource SHOULD NOT load all the data for the drop down list. Preferably, click on a dropdown arrow should not load any data, but from the examples it seems that it can't be done.
  2. Typing a filter string should load ONLY items that satisfy the filter.
  3. It SHOULD NOT raise an error in a case when there is no data which satisfy the filter.

Thanks,
Tom



KR Keerthana Rajendran Syncfusion Team April 19, 2018 04:51 PM UTC

Hi Tomislav, 
 
We have prepared a sample based on your requirement. 
Query 1: Initial loading of a datasource SHOULD NOT load all the data for the drop down list. Preferably, click on a dropdown arrow should not load any data, but from the examples it seems that it can't be done. 
Response: As we have processed the popupListItems in source during search , preventing data load and rendering empty popup on click will result in error during filter search. So, we request you to set a minimum itemsCount 1 or 2 to prevent loading of large data and remaining items will be filtered based on search in input box. 
Query 2:Typing a filter string should load ONLY items that satisfy the filter 
Response: We have overridden filter search method of DropDownList to filter items based on your return statement in controller. Please refer to the below given code 
    <td> 
            @(Html.EJ().DropDownList("Customers2") 
                .Datasource(ds => ds.URL("/DropDownList/CustomersDataSource2").Adaptor("UrlAdaptor")) 
                .DropDownListFields(f => f.Value("CustomerID").Text("CustomerID")) 
                .EnableServerFiltering(true) 
                .EnableFilterSearch(true) 
                .EnableIncrementalSearch(true) 
                .LoadOnDemand(true) 
                .AllowVirtualScrolling(true).ItemsCount(3) 
            ) 
        </td> 
     
<script>   
    ej.DropDownList.prototype._filterSearch = function (searchQuery, args) { 
        var flag = false; 
        this.resultList = args.result.result ? args.result.result : ej.DataManager(this._rawList).executeLocal(searchQuery); 
        if (this.resultList.length == 0) { 
            flag = true; 
            this.resultList.push(this._getLocalizedLabels("emptyResultText")); 
        } 
        this.popupListItems = this.resultList; 
        this.ultag.empty(); 
        this._isPlainType(this.popupListItems) ? this._plainArrayTypeBinding(this.resultList) : 
            this._objectArrayTypeBinding(this.resultList, "search"); 
        if (flag && this.ultag.find("li").length == 1) { 
            this.ultag.find("li").eq(0).addClass("e-nosuggestion"); 
        } 
        if (this.model.showCheckbox && !flag) { 
            this._appendCheckbox(this._getLi()); 
        } 
        this._onSearch = true; 
        var value = this.value(), visibleText = this._visibleInput[0].value; 
        this._setValue(this.value()); 
        var checkVal = typeof this.model.value === "function" ? this.model.value() : this.model.value; 
        if (checkVal != value) { 
            this.element[0].value = value; 
            this._visibleInput[0].value = visibleText; 
            this.model.text = visibleText == "" ? null : visibleText; 
            if (this.value() != value && !(this.value() == null && value == "")) { 
                this._updateValue(value); 
            } 
        } 
        this._onSearch = false; 
        this._updateSelectedIndexByValue(this.value()); 
        this._refreshScroller(); 
        this._setListPosition(); 
    } 
     
</script> 
 
 
Query 3: It SHOULD NOT raise an error in a case when there is no data which satisfy the filter. 
Response: In this case when no data matches , no suggestions text will  be shown in popup. Please refer to the below image 
 
 
 
We have attached the modified sample in the below link              
 
 
Regards, 
Keerthana. 



TT Tomislav Tustonic April 19, 2018 09:14 PM UTC

Hello

Thanks for the sample. It almost works, but not completely.
When I set ItemsCount(1) for the dropdownlist, and start typing filter, I only get one result. Is it possible to get ALL the results satisfying filter?\
In the image below, it should return all customers which start or contains letter 'W'. Typing more letters should reduce the number of items in the dropdown list.

Thanks, Tom



KR Keerthana Rajendran Syncfusion Team April 20, 2018 06:44 AM UTC

Hi Tomislav,   
   
Query: When I set ItemsCount(1) for the dropdownlist, and start typing filter, I only get one result. Is it possible to get ALL the results satisfying filter?   
   
Response: By default, itemsCount will considered during filtering data and data will be fetched based on this count. If you wish to load all the results satisfying the filter, you can modify the itemsCount to 0 in search event of DropDownList as shown below.   
   
<table>   
    <tr>   
       
        <td>   
            @(Html.EJ().DropDownList("Customers2")   
            .Datasource(ds => ds.URL("/DropDownList/CustomersDataSource2").Adaptor("UrlAdaptor"))   
            .DropDownListFields(f => f.Value("CustomerID").Text("CustomerID"))   
            .EnableServerFiltering(true)   
            .EnableFilterSearch(true)   
            .EnableIncrementalSearch(true)   
            .LoadOnDemand(true)   
            .AllowVirtualScrolling(true).ItemsCount(3).ClientSideEvents(e => e.Search("onSearch"))   
            )   
        </td>   
    </tr>   
</table>   
<script>     
    function onSearch(args) {   
        this.model.itemsCount = 0   
    }   
    ej.DropDownList.prototype._filterSearch = function (searchQuery, args) {   
        var flag = false;   
        this.resultList = args.result.result ? args.result.result : ej.DataManager(this._rawList).executeLocal(searchQuery);   
        if (this.resultList.length == 0) {   
            flag = true;   
            this.resultList.push(this._getLocalizedLabels("emptyResultText"));   
        }   
        …………………………….   
    }   
       
</script>   
   
   
Query: In the image below, it should return all customers which start or contains letter 'W'. Typing more letters should reduce the number of items in the dropdown list.   
   
Response: Now on typing “w” all items will be loaded as shown below.  
   
    
Typing more letters will reduce the number of items as shown below   
   
    
   
Regards,                                                                        
Keerthana.   
 


Loader.
Up arrow icon