Getting started with the KendoReact Sortable

The Sortable provides a sortable drag-and-drop functionality to elements within a list.

The KendoReact Sortable component is part of the KendoReact library of React UI components. It is distributed through NPM under the kendo-react-sortable package.

Basic Usage

The following example demonstrates the Sortable in action.

import React from 'react';
import ReactDOM from 'react-dom';
import { Sortable } from '@progress/kendo-react-sortable';

const getBaseItemStyle = (isActive) => ({
    height: 70,
    lineHeight: '68px',
    fontSize: '16px',
    textAlign: 'center',
    outline: 'none',
    border: '1px solid',
    cursor: 'move',
    display: 'inline-block',
    background: isActive ? '#27aceb' : '#bfe7f9',
    color: isActive ? '#fff' : '#1494d0',
    borderColor: isActive ? '#27aceb' : '#fff'
});

const SortableItemUI = (props) => {
    const { isDisabled, isActive, style, attributes, dataItem, forwardRef } = props;
    const classNames = [ 'col-xs-6 col-sm-3' ];

    if (isDisabled) {
        classNames.push('k-state-disabled');
    }

    return (
        <div
            ref={forwardRef}
            {...attributes}
            style={{
                ...getBaseItemStyle(isActive),
                ...style
            }}
            className={classNames.join(' ')}
        >
            {dataItem.text}
        </div>
    );
};

class App extends React.Component {
    state = {
        data: [
            { id: 1, text: 'item1' },
            { id: 2, text: 'item2' },
            { id: 3, text: 'item3' },
            { id: 4, text: 'item4' },
            { id: 5, text: 'item5' },
            { id: 6, text: 'item6' },
            { id: 7, text: 'item7' },
            { id: 8, text: 'item8' }
        ]
    };

    onDragOver = (event) => {
        this.setState({
            data: event.newState
        });
    }

    onNavigate = (event) => {
        this.setState({
            data: event.newState
        });
    }

    render() {
        return (
            <div className="container-fluid">
                <div className="example-config">
                    <h6>Items: {JSON.stringify(this.state.data)}</h6>
                </div>
                <Sortable
                    idField={'id'}
                    disabledField={'disabled'}
                    data={this.state.data}

                    itemUI={SortableItemUI}

                    onDragOver={this.onDragOver}
                    onNavigate={this.onNavigate}
                />
            </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Functionality and Features

Installation

  1. Download and install the package. Use Node.js v5.0.0 or later.

    npm install --save @progress/kendo-react-sortable
  2. Once installed, import the package module.

    // ES2015 module syntax
    import { Sortable } from '@progress/kendo-react-sortable';
    // CommonJS format
    const { Sortable } = require('@progress/kendo-react-sortable');
  3. You are required to install one of the Kendo UI themes to style your components. For more information on how to add the styles, refer to the article on getting started.

Dependencies

The Sortable package requires the following peer dependencies that have to be installed by your application:

  • react
  • react-dom

Events

The following example demonstrates basic Sortable events.

import React from 'react';
import ReactDOM from 'react-dom';
import { Sortable } from '@progress/kendo-react-sortable';

const getBaseItemStyle = (isActive) => ({
    height: 70,
    lineHeight: '68px',
    fontSize: '16px',
    textAlign: 'center',
    outline: 'none',
    border: '1px solid',
    cursor: 'move',
    display: 'inline-block',
    background: isActive ? '#27aceb' : '#bfe7f9',
    color: isActive ? '#fff' : '#1494d0',
    borderColor: isActive ? '#27aceb' : '#fff'
});

const SortableItemUI = (props) => {
    const { isDisabled, isActive, style, attributes, dataItem, forwardRef } = props;
    const classNames = [ 'col-xs-6 col-sm-3' ];

    if (isDisabled) {
        classNames.push('k-state-disabled');
    }

    return (
        <div
            ref={forwardRef}
            {...attributes}
            style={{
                ...getBaseItemStyle(isActive),
                ...style
            }}
            className={classNames.join(' ')}
        >
            {dataItem.text}
        </div>
    );
};

class App extends React.Component {
    state = {
        data: [
            { id: 1, text: 'item1' },
            { id: 2, text: 'item2' },
            { id: 3, text: 'item3' },
            { id: 4, text: 'item4' },
            { id: 5, text: 'item5' },
            { id: 6, text: 'item6' },
            { id: 7, text: 'item7' },
            { id: 8, text: 'item8' }
        ],
        events: []
    };
    element;

    componentDidUpdate() {
        this.element.scrollTop = this.element.scrollHeight;
    }

    onDragStart = (event) => {
        this.setState({
            events: [
                ...this.state.events,
                `Drag start: previous index:${event.prevIndex}`
            ]
        });
    }

    onDragOver = (event) => {
        this.setState({
            data: event.newState,
            events: [
                ...this.state.events,
                `Drag over: previous index:${event.prevIndex}, next index: ${event.nextIndex}`
            ]
        });
    }

    onDragEnd = (event) => {
        this.setState({
            events: [
                ...this.state.events,
                `Drag end: previous index:${event.prevIndex}, next index: ${event.nextIndex}`
            ]
        });
    }

    onNavigate = (event) => {
        this.setState({
            data: event.newState,
            events: [
                ...this.state.events,
                `Keyboard navigation: previous index:${event.prevIndex}, next index: ${event.nextIndex}`
            ]
        });
    }

    assignRef = (element) => {
        this.element = element;
    }

    render() {
        return (
            <div className="container-fluid">
                <Sortable
                    idField={'id'}
                    disabledField={'disabled'}
                    data={this.state.data}

                    itemUI={SortableItemUI}

                    onDragStart={this.onDragStart}
                    onDragOver={this.onDragOver}
                    onDragEnd={this.onDragEnd}
                    onNavigate={this.onNavigate}
                />
                <div className={'example-config'} style={{ marginTop: 20 }}>
                    <ul className={'event-log'} ref={this.assignRef}>
                        {this.state.events.map((event, idx) => <li key={idx}>{event}</li>)}
                    </ul>
                </div>
            </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
 /