React List - Scrolling

User Interaction

An end user can scroll the List with a swipe gesture and with the scrollbar. Although by default the swipe gesture is active for mobile devices and the scrollbar is active for desktops, you can force any or both of them to be used on all platforms. For this purpose, set the scrollByContent or scrollByThumb property to true.

jQuery
JavaScript
$(function() {
    $("#listContainer").dxList({
        // ...
        scrollByContent: true, // the swipe gesture on all platforms
        scrollByThumb: true // the scrollbar on all platforms
    });
});
Angular
HTML
TypeScript
<dx-list ...
    [scrollByContent]="true" <!-- the swipe gesture on all platforms -->
    [scrollByThumb]="true"> <!-- the scrollbar on all platforms -->
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        :scroll-by-content="true" <!-- the swipe gesture on all platforms -->
        :scroll-by-thumb="true" <!-- the scrollbar on all platforms -->
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';
import List from 'devextreme-react/list';

export default function App() {
    return (
        <List ...
            scrollByContent={true} {/* the swipe gesture on all platforms */}
            scrollByThumb={true} {/* the scrollbar on all platforms */}
        />
    );
}

The List employs native scrolling on most platforms, except non-Mac desktops and devices based on Android older than version 4. To employ native scrolling on all platforms without exception, assign true to the useNativeScrolling property. Note that if you assign false to this property, the List will simulate scrolling on all platforms.

jQuery
JavaScript
$(function() {
    $("#listContainer").dxList({
        // ...
        useNativeScrolling: true
    });
});
Angular
HTML
TypeScript
<dx-list ...
    [useNativeScrolling]="true">  
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        :use-native-scrolling="true"
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';
import List from 'devextreme-react/list';

export default function App() {
    return (
        <List ...
            useNativeScrolling={true}
        />
    );
}

If simulated scrolling is used, you can specify when to show the scrollbar. For this purpose, use the showScrollbar property.

jQuery
JavaScript
$(function() {
    $("#listContainer").dxList({
        // ...
        useNativeScrolling: false,
        showScrollbar: 'always' // or 'onScroll' | 'onHover' | 'never'
    });
});
Angular
HTML
TypeScript
<dx-list ...
    [useNativeScrolling]="false"
    showScrollbar="always"> <!-- or "onScroll" | "onHover" | "never" -->
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        :use-native-scrolling="false"
        show-scrollbar="always" <!-- or "onScroll" | "onHover" | "never" -->
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';
import List from 'devextreme-react/list';

export default function App() {
    return (
        <List ...
            useNativeScrolling={true}
            showScrollbar="always" {/* or "onScroll" | "onHover" | "never" */}
        />
    );
}

On mobile devices, the user can pull the List to scroll it slightly further than its top or bottom boundary. Once the user releases the List, it bounces back to the boundary position. You can disable this effect using the bounceEnabled property.

jQuery
JavaScript
$(function() {
    $("#listContainer").dxList({
        // ...
        bounceEnabled: false
    });
});
Angular
HTML
TypeScript
<dx-list ...
    [bounceEnabled]="false">  
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        :bounce-enabled="false"
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';
import List from 'devextreme-react/list';

export default function App() {
    return (
        <List ...
            bounceEnabled={false}
        />
    );
}

If you want to disable scrolling completely, assign false to the scrollingEnabled property.

jQuery
JavaScript
$(function() {
    $("#listContainer").dxList({
        // ...
        scrollingEnabled: false
    });
});
Angular
HTML
TypeScript
<dx-list ...
    [scrollingEnabled]="false">  
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        :scrolling-enabled="false"
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';
import List from 'devextreme-react/list';

export default function App() {
    return (
        <List ...
            scrollingEnabled={false}
        />
    );
}
See Also

API

The following table gives an overview of scrolling-related methods exposed by the List.

Method Description
scrollHeight() Returns the height of the scrollable content in pixels.
scrollToItem(itemIndex) Scrolls the List to the item with a specific index.
scrollToItem(itemElement) Scrolls the List to a specific DOM node.
scrollTo(location) Scrolls the List to a location specified in pixels.
scrollBy(distance) Scrolls the List from the current location by a distance specified in pixels.
scrollTop() Returns a pixel-measured value that shows how far the List is scrolled from the top.

The following examples shows how to call these methods.

jQuery
JavaScript
const list = $("#listContainer").dxList("instance");
const listItems = list.option("items");

// Scrolls the List to the last item
list.scrollToItem(listItems.length-1);

// Scrolls a grouped List to the first item of the last group
list.scrollToItem({
    group: listItems.length-1,
    item: 0
});
JavaScript
// Finds the DOM nodes of all items and scrolls the List to the last node
const listItemNodes = $("#listContainer").find(".dx-list-item");
list.scrollToItem(listItemNodes[listItemNodes.length-1]);

// Finds the DOM nodes of all groups and scrolls the List to the last node
const listGroupNodes = $("#listContainer").find(".dx-list-group");
list.scrollToItem(listGroupNodes[listGroupNodes.length-1]);
JavaScript
const contentHeight = list.scrollHeight();
const scrolledFromTopBy = list.scrollTop();
list.scrollTo(200);
list.scrollBy(100);
Angular
TypeScript
import { ..., ViewChild } from "@angular/core";
import { DxListModule, DxListComponent } from "devextreme-angular";
// ...
export class AppComponent {
    @ViewChild(DxListComponent, { static: false }) list: DxListComponent;
    // Prior to Angular 8
    // @ViewChild(DxListComponent) list: DxListComponent;
    scrollToLastItem() {
        const listItems = this.list.instance.option("items");
        this.list.instance.scrollToItem(listItems.length-1);
        // OR
        // Find the DOM nodes of all items and scroll to the last node
        const listItemNodes = document.getElementsByClassName("dx-list-item");
        this.list.instance.scrollToItem(listItemNodes[listItemNodes.length-1]);
    }
    scrollToLastGroup() {
        const listItems = this.list.instance.option("items");
        this.list.instance.scrollToItem({
            group: listItems.length-1,
            item: 0
        });
        // OR
        // Find the DOM nodes of all groups and scroll to the last node
        const listGroupNodes = document.getElementsByClassName("dx-list-group");
        this.list.instance.scrollToItem(listGroupNodes[listGroupNodes.length-1]);
    }
    getListHeight() {
        return this.list.instance.scrollHeight();
    }
    getScrolledDistanceFromTop() {
        return this.list.instance.scrollTop();
    }
    scrollTo() {
        this.list.instance.scrollTo(200);
    }
    scrollBy() {
        this.list.instance.scrollBy(100);
    }
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        :ref="listRefKey"
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

const listRefKey = "my-list";
// ...
export default {
    components: {
        DxList
    },
    data() {
        return {
            // ...
            listRefKey
        }
    },
    methods: {
        scrollToLastItem() {
            const listItems = this.list.option("items");
            this.list.scrollToItem(listItems.length-1);
            // OR
            // Find the DOM nodes of all items and scroll to the last node
            const listItemNodes = document.getElementsByClassName("dx-list-item");
            this.list.scrollToItem(listItemNodes[listItemNodes.length-1]);
        },
        scrollToLastGroup() {
            const listItems = this.list.option("items");
            this.list.scrollToItem({
                group: listItems.length-1,
                item: 0
            });
            // OR
            // Find the DOM nodes of all groups and scroll to the last node
            const listGroupNodes = document.getElementsByClassName("dx-list-group");
            this.list.scrollToItem(listGroupNodes[listGroupNodes.length-1]);
        },
        getListHeight() {
            return this.list.scrollHeight();
        },
        getScrolledDistanceFromTop() {
            return this.list.scrollTop();
        },
        scrollTo() {
            this.list.scrollTo(200);
        },
        scrollBy() {
            this.list.scrollBy(100);
        }
    },
    computed: {
        list: function() {
            return this.$refs[listRefKey].instance;
        }
    }
}
</script>
React
App.js
import React, { useRef } from 'react';
import 'devextreme/dist/css/dx.light.css';

import List from 'devextreme-react/list';
// ...
export default function App() {
    const list = useRef(null);
    const scrollToLastItem = () => {
        const listItems = list.current.instance.option("items");
        list.current.instance.scrollToItem(listItems.length-1);
        // OR
        // Find the DOM nodes of all items and scroll to the last node
        const listItemNodes = document.getElementsByClassName("dx-list-item");
        list.current.instance.scrollToItem(listItemNodes[listItemNodes.length-1]);
    };
    const scrollToLastGroup = () => {
        const listItems = list.current.instance.option("items");
        list.current.instance.scrollToItem({
            group: listItems.length-1,
            item: 0
        });
        // OR
        // Find the DOM nodes of all groups and scroll to the last node
        const listGroupNodes = document.getElementsByClassName("dx-list-group");
        list.current.instance.scrollToItem(listGroupNodes[listGroupNodes.length-1]);
    };
    const getListHeight = () => {
        return list.current.instance.scrollHeight();
    };
    const getScrolledDistanceFromTop = () => {
        return list.current.instance.scrollTop();
    };
    const scrollTo = () => {
        list.current.instance.scrollTo(200);
    };
    const scrollBy = () => {
        list.current.instance.scrollBy(100);
    };
    return (
        <List ...
            ref={list}
        />
    );
}
See Also

Events

To execute certain commands when the List is scrolled, handle the scroll event. If the event handling function is not going to be changed during the lifetime of the UI component, assign it to the onScroll property when you configure the UI component.

jQuery
JavaScript
$(function () {
    $("#listContainer").dxList({
        // ...
        onScroll: function(e) {
            const scrollOffset = e.scrollOffset.top;
            const scrolledToTop = e.reachedTop;
            const scrolledToBottom = e.reachedBottom;
            // Handler of the "scroll" event
        }
    });
});
Angular
HTML
TypeScript
<dx-list ...
    (onScroll)="onScroll($event)">
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    onScroll (e) {
        const scrollOffset = e.scrollOffset.top;
        const scrolledToTop = e.reachedTop;
        const scrolledToBottom = e.reachedBottom;
        // Handler of the "scroll" event
    }
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxList ...
        @scroll="onListScroll"
    />
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    // ...
    methods: {
        onListScroll(e) {
            const scrollOffset = e.scrollOffset.top;
            const scrolledToTop = e.reachedTop;
            const scrolledToBottom = e.reachedBottom;
            // Handler of the "scroll" event
        }
    }
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';
import List from 'devextreme-react/list';

const onListScroll = (e) => {
    const scrollOffset = e.scrollOffset.top;
    const scrolledToTop = e.reachedTop;
    const scrolledToBottom = e.reachedBottom;
    // Handler of the "scroll" event
}

export default function App() {
    return (
        <List
            onScroll={onListScroll}
        />
    );
}

If you are going to change the scroll event handler at runtime, or if you need to attach several handlers to this event, subscribe to it using the on(eventName, eventHandler) method. This approach is more typical of jQuery.

JavaScript
const scrollEventHandler1 = function(e) {
    // First handler of the "scroll" event
};

const scrollEventHandler2 = function(e) {
    // Second handler of the "scroll" event
};

$("#listContainer").dxList("instance")
    .on("scroll", scrollEventHandler1)
    .on("scroll", scrollEventHandler2);
See Also