Virtual scroll - combobox with UrlAdaptor

Is there some example about how to use the "virtual scrolling" with the combobox which has UrlAdaptor for the datasource?

The combobox might be like this:





Thanks!
Bernard.

9 Replies 1 reply marked as answer

SN Sevvandhi Nagulan Syncfusion Team January 28, 2021 04:15 PM UTC

Hi Bernard, 


Greetings from Syncfusion support. 


We have checked your query performing virtual scrolling functionality using URL Adaptor in Combobox. We have made sample for your requirement. Please find the sample in the below link. 





Regards, 
Sevvandhi N 


Marked as answer

BJ Bernard Jurlina February 2, 2021 09:56 PM UTC

Excellent, 

thanks Sevvandhi. Your example is working great.
But, I have two more situations.

1. Scroll event not working if I show two columns in the combobox, like this:



2. Is there some whay to use queryString in the scroll event for the executeQuery?
Let's say I want to search last name like markov, and the combobox shows the data


but then I use the scroll event



and I want to use this.queryString in the executeQuery method to filter the results. 
Now, the returned data is like this:



It shows the data without the where filter.

Thanks!
Bernard.



SN Sevvandhi Nagulan Syncfusion Team February 3, 2021 12:54 PM UTC

Hi Bernard,  


 
Query 1: Scroll event not working if I show two columns in the combobox, like this:  
 
We checked the reported issue by customizing the popup with more than one column using Item Template. The data has been dynamically added when scrolling on the list element. Please refer the below code.  
 
   <ejs-combobox id="customers" placeholder="Select a customer"  itemTemplate="@Html.Raw("<span><span class='name'>${CustomerID}</span><span class ='order'>${OrderID}</span></span>")" query="new ej.data.Query().select(['CustomerID','OrderID']).take(10) "  allowFiltering="true" open="onOpen" filtering="onFiltering">  
            <e-combobox-fields text="CustomerID" value="OrderID"></e-combobox-fields>  
            <e-data-manager url="/Home/UrlDatasource" adaptor="UrlAdaptor" crossDomain="true"></e-data-manager>  
        </ejs-combobox>  
 
Query 2: Is there some whay to use queryString in the scroll event for the executeQuery?  
Let's say I want to search last name like markov, and the combobox shows the data  
 
 
We resolved the reported issue in the sample. Please refer the below code.  
 
 
function onOpen(args) { 
        if (!this.isInitial) { 
            var start = 7; 
            var end = 12 
            var instance = document.getElementById("customers").ej2_instances[0]; 
            var listElement = instance.popupObj.element.firstChild; 
            listElement.addEventListener('scroll', () => { 
                if ((listElement.scrollTop + listElement.offsetHeight >= listElement.scrollHeight && !isFiltered)) { 
                    var filterQuery = this.query.clone(); 
                    this.dataSource.executeQuery(filterQuery.range(start, end)).then((event) => { 
                        start = end; 
                        end += 5; 
                        instance.addItem(event.result); 
                    }).catch((e) => { 
                    }); 
                } 
            }) 
        } 
    } 
 
    function onFiltering(e) { 
               var instance = document.getElementById('customers').ej2_instances[0]; 
               var query = new ej.data.Query(); 
                query = (e.text !== '') ? query.where('CustomerID', 'startswith', e.text, true) : query; 
        e.updateData(instance.dataSource, query); 
        isFiltered = (e.text !== '') ? true : false; 
         
    } 
 
    function onChange(args) { 
        isFiltered = false; 
    } 
 
 
If you want to filter items based on multiple columns, then we suggest you use ‘Predicate’ of DataManager in the filtering event. Please refer the below code 
 
  var predicate = new ej.data.Predicate('CustomerID', 'startswith', e.text, true);  
    predicate = predicate.or('OrderID', 'startswith', e.text, true);  
    var dropdown_query = new ej.data.Query();  
    // frame the query based on search string with filter type.  
    dropdown_query = (e.text !== '') ? dropdown_query.where(predicate) : dropdown_query;  
    // pass the filter data source, filter query to updateData method.  
    e.updateData(instance.dataSource, dropdown_query);  
 
Please find the sample below.  
 
 
 
 
Please check the above sample and get back to us if you need further assistance.  
 
 
Regards,  
Sevvandhi N  



BJ Bernard Jurlina February 3, 2021 09:46 PM UTC

Hi Sevvandhi!

Great, your solution is working excellent!
But, try to add the headerTemplate, maybe like this:


Then, it won't work.

So, I have just one more problem.
Suppose you have more then one combobox on the page, like this:



and each one is loading the datasource as you described in your example. But, I want to open the first one, scroll down couple of times and then select some value.
After I selected it, I want that value to be selected on the other two comboboxes...but the problem is, the other comboboxes don't have expanded datasource like the first one. So, in other words, can I somehow set the datasource for the other comboboxes in the scroll event of the first one?

In your solution, try to add another combobox below the first one, use the same way to populate the datasource on scroll....and then open the first combobox, scroll down few times and select some value. Then select that value and in the second combobox.

I hope I explained it well.

Thanks!
Bernard.


SN Sevvandhi Nagulan Syncfusion Team February 4, 2021 03:39 PM UTC


Hi Bernard, 


Query 1: Great, your solution is working excellent! 
But, try to add the headerTemplate, maybe like this: 


We checked your query.  We can reproduce the reported issue in our end. We suggest that you to modify the code in the open event to get rid of the reported issue. Please refer the below code. 


function onOpen(args) { 
        if (!this.isInitial) { 
            var start = 7; 
            var end = 12 
            var instance = document.getElementById("customers").ej2_instances[0]; 
            var listElement = instance.popupObj.element.querySelector('.e-content'); 
            listElement.addEventListener('scroll', () => { 
                if ((listElement.scrollTop + listElement.offsetHeight >= listElement.scrollHeight && !isFiltered)) { 
                    var filterQuery = this.query.clone(); 
                    this.dataSource.executeQuery(filterQuery.range(start, end)).then((event) => { 
                        start = end; 
                        end += 5; 
                        instance.addItem(event.result); 
                    }).catch((e) => { 
                    }); 
                } 
            }) 
        } 
    } 



Query 2: So, I have just one more problem. 
Suppose you have more then one combobox on the page, like this: 


We provided the custom value support to ComboBox component. So you can assign the value to the second and third combobox in the first component’s change event. Please refer the below code. 


 
        <div class='content'> 
            <ejs-combobox id="customers" placeholder="Select a customer" headerTemplate="@Html.Raw("<span><span class='name'>CustomerID</span><span class ='order'>OrderID</span></span>")" itemTemplate="@Html.Raw("<span><span class='name'>${CustomerID}</span><span class ='order'>${OrderID}</span></span>")" query="new ej.data.Query().select(['CustomerID','OrderID']).take(10) " allowFiltering="true" open="onOpen" change="onChange" filtering="onFiltering"> 
                <e-combobox-fields text="CustomerID" value="OrderID"></e-combobox-fields> 
                <e-data-manager url="/Home/UrlDatasource" adaptor="UrlAdaptor" crossDomain="true"></e-data-manager> 
            </ejs-combobox> 
        </div> 
        <div class='content'> 
            <ejs-combobox id="customers1" placeholder="Select a customer" headerTemplate="@Html.Raw("<span><span class='name'>CustomerID</span><span class ='order'>OrderID</span></span>")" itemTemplate="@Html.Raw("<span><span class='name'>${CustomerID}</span><span class ='order'>${OrderID}</span></span>")" query="new ej.data.Query().select(['CustomerID','OrderID']).take(10) " allowFiltering="true"> 
                <e-combobox-fields text="CustomerID" value="OrderID"></e-combobox-fields> 
                <e-data-manager url="/Home/UrlDatasource" adaptor="UrlAdaptor" crossDomain="true"></e-data-manager> 
            </ejs-combobox> 
        </div> 
    </div> 
    function onChange(args) { 
        isFiltered = false; 
 
        var instance = document.getElementById("customers1").ej2_instances[0]; 
 
        instance.value = args.itemData.CustomerID; 
 
    } 



Please find the sample below. 




Regards, 
Sevvandhi N 



BJ Bernard Jurlina February 6, 2021 08:35 AM UTC

Hi Sevvandhi!

I try to modify your project, but it's not working well. Can you please check it?
What I want to do is to load some other data Customer, with the data from 1 to 20 for CustomerId and from AAA to JJJ for the customer Name.

But, why it won't load the data after CustomerId = 10? It keeps loading the data from the beginning. Just try to scroll the first combobox and you'll get the point.
So, if you can repair that, the second thing what I want to check is....to scroll down the first combo to the end and then select the customer SSS and check if that customer can be selected in the second combo also...but without the opening the second combo.

In short, start...open first combo....select the value SSS...and check the selected value for the second combo.

Thanks!

Regards,
Bernard.

Attachment: WebApplication1_bernard_4d49bcd5.zip


SN Sevvandhi Nagulan Syncfusion Team February 9, 2021 03:52 PM UTC

 
Hi Bernard, 


We are currently validating the reported requirement. We will update further details on February 11th,2021 . We appreciate your patience until then. 


Regards, 
Sevvandhi N 



EM Emiliano February 11, 2021 12:09 PM UTC

I am waiting for the virtual scrolling for combobox and dropdownlist too. I have some tables with thousand of records and i need this behaviour in this components.
I tryed the code from here and noticed that it have some problems, that i corrected and made some improvements too.

Problems:
The 'onFiltering' function register new scroll listerners as many times you open the combobox.
If you filter, it returns all elements in one go, instead of doing the virtual scrolling.
If you filter by some text it returns all elements, but if you delete the filtering text, the list presented have the first 10 record returned initially, and the filtered records returned with the previous text filtering.
If you scroll and return some records, if you close and open again, the first 10 elements are ok, but the next 10 elements, are sorted in the wrong order. and the next 10...
If you pass a value from the modelview to the ejs-for ou value in the ejs-combobox, the combobox shows the value and not the corresponding text.

With my code, i dont have hardcoded fields in the javascript functions, the virtual scrolling is working ok with no text filter and with text filter. But i still have problems with the order of the list when i open and close the combobox.
I am using aspnetmvc and the comboboxfor shows the correct text for the selected value passed by my modelview.

My code:

function onOpen2(args) {
        console.log('onOpen2');
        if (!this.isInitial) {
            var instance = this.element.ej2_instances[0];
            var listElement = instance.popupObj.element.getElementsByClassName('e-dropdownbase')[0];
            listElement.addEventListener('scroll', () => {
                if ((listElement.scrollTop + listElement.offsetHeight >= listElement.scrollHeight)) {
                    var filterQuery = (this.typedString !== '') ? this.query.clone().where(this.fields.text, 'contains', this.typedString, true) : new ej.data.Query();
                    let start = this.element.ej2_instances[0].listData.length;
                    let end = start + 10
                    console.log(`Get records from ${start} to ${end}`);
                    this.dataSource.executeQuery(filterQuery.range(start, end)).then((event) => {
                        instance.addItem(event.result);
                        this.isInitial = true; //So it cannot register another listener when popup is opened again.
                    }).catch((e) => {
                    });
                }
            })
        }
    }

    function onFiltering2(e) {
        console.log('onFiltering2');
        var instance = this.element.ej2_instances[0];
        var query = instance.query;
        query.queries = query.queries.filter(item => item.fn != 'onWhere');
        if (e.text !== '') {
            query = query.where(this.fields.text, 'contains', e.text, true);
        }
        e.updateData(instance.dataSource, query);
    }

    function onChange2(args) {
        console.log('onChange2');
        var instance = this.element.ej2_instances[0];
        instance.value = args.value;
    }

just want to help other people out there. see my example to check the diferences, between what was posted here and my development.


Attachment: EJ2_Asp.Core_Comboxbox_with_url_adaptor_and_virtual_scrolling_faa25af5.zip


SN Sevvandhi Nagulan Syncfusion Team February 13, 2021 09:56 AM UTC

Hi Bernard / Emiliano,    

    
We considered the reported requirement “Provide support to virtual scrolling for DropDown components” as feature at our end and this support will be included in any one of our upcoming releases. We will implement the feature based on the customer request count and priority.   
  
   
You can track the status of the requested requirement from the below feedback link.   

   
    
   
To make it count, please cast your vote. We will prioritize the features based on the demands of each release.  If you have more specifications / suggestions on the request for the feature, you can add it to the portal as a comment.    

    
Regards,    
Sevvandhi N  



Loader.
Up arrow icon