Virtualization

Virtual scrolling provides an alternative to paging and is useful for displaying large sets of data.

The virtualization functionality uses a fixed amount of list items in the pop-up list of the component. While the user is scrolling the pop-up list, the DropDownList requests and displays only the visible items.

To enable virtualization, configure pagechange event and the composite virtual property which contains the following fields:

  • total—Represents the number of records.
  • skip—Represents the start of the sub-set of data which is loaded in the DropDownList.
  • pageSize—Indicates the size of the sub-set of data.
  • onPageChange—Provides the data for each page through the onPageChange event handler.
  • In order for the virtualization to work properly, the items in the popup list must have the same height. If the content of an item does not fit in a single row, the height of this item will be different from the height of the other items.
  • You also need to make sure that the pageSize value is at least equal to the number of the visible pop-up items plus two.

Basic Configuration

The following example demonstrates how to set the virtualization of the DropDownList.

<div id="vueapp" class="vue-app">
      <dropdownlist
                    :data-items="subsetData"
                    :text-field="'text'"
                    :data-item-key="'id'"
                    :virtual="virtual"
                    @pagechange="pageChange"
                    :popup-settings="popupSettings"
                >
      </dropdownlist>
</div>
import { DropDownList } from '@progress/kendo-vue-dropdowns';
Vue.component('dropdownlist', DropDownList);


new Vue({
    el: '#vueapp',
    data: function () {
        return {
            allData: [],
            subsetData: [],
            total: 5000,
            pageSize: 12,
            skip: 0,
            popupSettings: {
                height: '250px'
            }
        };
    },
      created() {
        for (let i = 0; i < this.total; i++) {
            this.allData.push({ id: i, text: 'Item ' + i });
        }
        this.subsetData = this.allData.slice(0, this.pageSize);
    },
    computed: {
        virtual: function() {
            return {
                pageSize: this.pageSize,
                skip: this.skip,
                total: this.total
            };
        }
    },
    methods: {
         pageChange(event) {
            const skip = event.page.skip;
            const take = event.page.take;
            const newSubsetData = this.allData.slice(skip, skip + take);
            this.subsetData = newSubsetData;
            this.skip = skip;
        }
    }
});

Virtualization with Filtering

If you use virtualization in your project alongside filtering, scrolling will be reset every time the value of the filter input is changed.

<div id="vueapp" class="vue-app">
    <dropdownlist
        :data-items="subsetData"
        :data-item-key="'id'"
        :text-field="'text'"
        :filterable="true"
        @filterchange="onFilterChange"
        :virtual="virtual"
        :popup-settings="popupSettings"
        @pagechange="pageChange"
    >
    </dropdownlist>
</div>
import Vue from 'vue';
import { DropDownList } from '@progress/kendo-vue-dropdowns';
import { filterBy } from '@progress/kendo-data-query';

const total = 5000;
const pageSize = 11;
const allData = [];

for (let i = 0; i < total; i++) {
    allData.push({ id: i, text: 'Item ' + i });
}

Vue.component('dropdownlist', DropDownList);

new Vue({
    el: '#vueapp',
    data: function () {
        return { 
            filteredData: [],
            skip: 0,
            total: total,
            subsetData: allData.slice(0, pageSize),
            popupSettings: {
                height: '210px'
            }
        };
    },
    created(){
        this.filteredData = allData.slice();
    },
    computed: {
        virtual: function(){
            return {
                total: this.total,
                pageSize: pageSize,
                skip: this.skip
            };
        }
    },
    methods: {
        onFilterChange: function(event) {
            this.filteredData = filterBy(allData.slice(), event.filter);
    
            const data = this.filteredData.slice(0, pageSize);
    
            this.subsetData= data;
            this.skip = 0;
            this.total = this.filteredData.length;
        },
        pageChange: function(event) {
            const skip = event.page.skip;
            const take = event.page.take;
            const newSubsetData = this.filteredData.slice(skip, skip + take);
    
            this.subsetData = newSubsetData;
            this.skip = skip;
        }
    }
});

In this article