All Components

This website hosts native Kendo UI components, built from the ground up with the ultimate performance in mind, intended to be used in the React ecosystem.

DropDownList Overview

The DropDownList is a form component that lets you choose a single predefined value from a list.

It is a richer version of the <select> element and supports filtering, default items, and virtualization.

Basic Usage

The following example demonstrates the DropDownList in action.

import React from 'react';
import ReactDOM from 'react-dom';

import { DropDownList } from '@progress/kendo-react-dropdowns';

class AppComponent extends React.Component {
    sizes = [ "X-Small", "Small", "Medium", "Large", "X-Large", "2X-Large" ];

    render() {
        return (
            <div>
                <div>T-shirt size:</div>
                <DropDownList data={this.sizes} />
            </div>
        );
    }
}

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

Functionality and Features

Events

The DropDownList provides events which:

Common Usage

The following example demonstrates basic DropDownList events.

import React from 'react';
import ReactDOM from 'react-dom';
import { DropDownList } from '@progress/kendo-react-dropdowns';

class AppComponent extends React.Component {
    source = [ "Albania", "Andorra", "Armenia", "Austria", "Azerbaijan" ];

    constructor(props) {
        super(props);

        this.state = {
            events: []
        };

        this.onOpen = this.onOpen.bind(this);
        this.onClose = this.onClose.bind(this);
        this.onFocus = this.onFocus.bind(this);
        this.onBlur = this.onBlur.bind(this);
        this.onChange = this.onChange.bind(this);
        this.onFilterChange = this.onFilterChange.bind(this);
    }

    onOpen() { this.log('open'); }
    onClose() { this.log('close'); }
    onFocus() { this.log('focus'); }
    onBlur() { this.log('blur'); }
    onChange(event) { this.log('change', event.target.value); }
    onFilterChange(event) { this.log('filterChange', event.filter.value); }

    render() {
        return (
            <div>
                <DropDownList
                    data={this.source}
                    onOpen={this.onOpen}
                    onClose={this.onClose}
                    onFocus={this.onFocus}
                    onBlur={this.onBlur}
                    onChange={this.onChange}
                    onFilterChange={this.onFilterChange}
                    filterable={true}
                />
                <br />
                <br />
                <EventsLogger events={this.state.events} />
            </div>
        );
    }

    log(event, arg) {
        const events = this.state.events;
        events.unshift(`${event} ${arg || ""}`);

        this.setState({
            events: events
        });
    }
}

class EventsLogger extends React.Component {
    render() {
        return (
            <div class="example-config">
                <h5>Event log</h5>
                <ul class="event-log" style={{ textAlign: 'right' }}>
                    {this.props.events.map(function(event, index) {
                        return (<li key={index}>{event}</li>);
                    })}
                </ul>
            </div>
        );
    }
}

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

Looping through Items

By default, you can select a DropDownList item by pressing a keyboard key. For example, if the DropDownList items are Foo, Bar, and Baz and the user presses the B letter key, based on the alphabetical order of the items, the keypress selects the first item which starts with a B.

The keyboard selection is available only if the filtering functionality is disabled.

Common Scenarios

You can use the configuration options of the DropDownList to achieve the implementation of common scenarios such as:

Controlling the DropDownList Value

You can use the DropDownList as the so-called "controlled component" in React which is similar to the behavior of the native <select> element.

import React from 'react';
import ReactDOM from 'react-dom';

import { DropDownList } from '@progress/kendo-react-dropdowns';

class AppComponent extends React.Component {
    sizes = [ "X-Small", "Small", "Medium", "Large", "X-Large", "2X-Large" ];

    constructor(props) {
        super(props);
        this.state = {
            value: ''
        };

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        this.setState({
            value: event.target.value
        });
    }

    render() {
        return (
            <div>
                <div>T-shirt size:</div>
                <DropDownList
                    data={this.sizes}
                    value={this.state.value}
                    onChange={this.handleChange}
                />
            </div>
        );
    }
}

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

Implementing Cascading DropDownLists

The cascading DropDownList is a series of two or more DropDownLists where each DropDownList is filtered based on the selected option from the previous DropDownList.

import React from 'react';
import ReactDOM from 'react-dom';
import { DropDownList } from '@progress/kendo-react-dropdowns';
import { dataCategories, dataProducts, dataOrders } from './data.js';

const defaultItemCategory = { categoryName: 'Select Category ...' };
const defaultItemProduct = { productName: 'Select Product ...' };
const defaultItemOrder = { orderName: 'Select Order ...' };

class AppComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            category: null,
            product: null,
            order: null,
            orders: dataOrders,
            products: dataProducts
        };

        this.categoryChange = this.categoryChange.bind(this);
        this.productChange = this.productChange.bind(this);
        this.orderChange = this.orderChange.bind(this);
    }

    categoryChange(event) {
        const category = event.target.value;
        const products = dataProducts.filter(product => product.categoryId === category.categoryId);

        this.setState({
            category: category,
            products: products,
            product: null,
            order: null
        });
    }

    productChange(event) {
        const product = event.target.value;
        const orders = dataOrders.filter(order => order.productId === product.productId);

        this.setState({
            product: product,
            orders: orders,
            order: null
        });
    }

    orderChange(event) {
        this.setState({ order: event.target.value });
    }

    render() {
        const category = this.state.category;
        const product = this.state.product;
        const order = this.state.order;

        const hasCategory = category && category !== defaultItemCategory;
        const hasProduct = product && product !== defaultItemProduct;

        return (
            <div>
                <div style={{ display: 'inline-block' }}>
                    Categories
                    <br />
                    <DropDownList
                        data={dataCategories}
                        textField={'categoryName'}
                        onChange={this.categoryChange}
                        defaultItem={defaultItemCategory}
                        value={category}
                    />
                </div>
                <div style={{ display: 'inline-block', marginLeft: '30px' }}>
                    Products
                    <br />
                    <DropDownList
                        disabled={!hasCategory}
                        data={this.state.products}
                        textField={'productName'}
                        onChange={this.productChange}
                        defaultItem={defaultItemProduct}
                        value={product}
                    />
                </div>
                <div style={{ display: 'inline-block', marginLeft: '30px' }}>
                    Orders
                    <br />
                    <DropDownList
                        disabled={!hasProduct}
                        data={this.state.orders}
                        textField={'orderName'}
                        onChange={this.orderChange}
                        defaultItem={defaultItemOrder}
                        value={order}
                    />
                </div>
            </div>
        );
    }
}

ReactDOM.render(
    <AppComponent />,
    document.querySelector('my-app')
);
const dataCategories = [
    { categoryName: "Beverages", categoryId: 1 },
    { categoryName: "Condiments", categoryId: 2 },
    { categoryName: "Seafood", categoryId: 3 }
];

const dataProducts = [
    { productName: "Chai", productId: 1, categoryId: 1 },
    { productName: "Chang", productId: 2, categoryId: 1 },
    { productName: "Aniseed Syrup", productId: 3, categoryId: 2 },
    { productName: "Genen Shouyu", productId: 4, categoryId: 2 },
    { productName: "Ikura", productId: 5, categoryId: 3 },
    { productName: "Konbu", productId: 6, categoryId: 3 }
];

const dataOrders = [
    { orderName: "Cunewalde", orderId: 1, productId: 1 },
    { orderName: "Albuquerque", orderId: 2, productId: 1 },
    { orderName: "Geneva", orderId: 3, productId: 2 },
    { orderName: "Graz", orderId: 4, productId: 2 },
    { orderName: "London", orderId: 5, productId: 3 },
    { orderName: "I. de Margarita", orderId: 6, productId: 3 },
    { orderName: "Barquisimeto", orderId: 7, productId: 4 },
    { orderName: "Brandenburg", orderId: 8, productId: 4 },
    { orderName: "Cunewalde", orderId: 9, productId: 5 },
    { orderName: "Mexico D.F.", orderId: 10, productId: 5 },
    { orderName: "Mexico D.F.", orderId: 11, productId: 6 },
    { orderName: "Rio de Janeiro", orderId: 12, productId: 6 }
];

export { dataCategories, dataProducts, dataOrders };

Using Remote Data with Virtualization and Filtering

The following example demonstrates how to configure the DropDownList to use remote data along with data caching, virtual scrolling, and filtering.

import React from 'react';
import ReactDOM from 'react-dom';
import { DropDownList } from '@progress/kendo-react-dropdowns';

const textField = 'ShipCity';
const valueField = 'OrderID';
const defaultItem = { [textField]: 'Select ...', [valueField]: null };
const emptyItem = { [textField]: 'loading ...' };
const pageSize = 9;

const loadingData = [];
while (loadingData.length < pageSize) {
    loadingData.push({ ...emptyItem });
}

class AppComponent extends React.Component {
    baseUrl = `https://odatasampleservices.azurewebsites.net/V4/Northwind/Northwind.svc/`;
    init = { method: 'GET', accept: 'application/json', headers: [] };
    dataCaching = [];
    pendingRequest;
    requestStarted = false;

    constructor(props) {
        super(props);

        this.state = {
            data: [],
            skip: 0,
            total: 0,
            filter: ''
        };
    }

    componentDidMount() {
        this.requestData(0, this.state.filter);
    }

    requestData(skip, filter) {
        if (this.requestStarted) {
            clearTimeout(this.pendingRequest);
            this.pendingRequest = setTimeout(() => { this.requestData(skip, filter); }, 50);
            return;
        }

        const url = this.baseUrl +
            `Orders?$filter=contains(ShipCity,'${filter}')&$skip=${skip}&$top=${pageSize}&$count=true`;

        this.requestStarted = true;
        fetch(url, this.init)
            .then(response => response.json())
            .then(json => {
                const total = json['@odata.count'];
                const items = [];
                json.value.forEach((element, index) => {
                    const { OrderID, ShipCity } = element;
                    const item = { [valueField]: OrderID, [textField]: ShipCity + ' ' + OrderID };
                    items.push(item);
                    this.dataCaching[index + skip] = item;
                });

                if (skip === this.state.skip) {
                    this.setState({
                        data: items,
                        total: total
                    });
                }
                this.requestStarted = false;
            });
    }

    onFilterChange = (event) => {
        const filter = event.filter.value;

        this.resetCach();
        this.requestData(0, filter);

        this.setState({
            data: loadingData,
            skip: 0,
            filter: filter
        });
    }

    pageChange = (event) => {
        const skip = event.page.skip;
        const filter = this.state.filter;

        let makeRequest = false;
        for (let i = 0; i < pageSize; i++) {
            if (!this.dataCaching[skip + i]) {
                makeRequest = true;
                break;
            }
        }

        if (makeRequest) {
            this.requestData(skip, filter);
        }

        const data = this.getCachedData(skip);

        this.setState({
            data: data,
            skip: skip
        });
    }

    render() {
        return (
            <div>
                <p>Orders</p>
                <DropDownList
                    data={this.state.data}
                    valueField={valueField}
                    textField={textField}
                    defaultItem={defaultItem}
                    filterable={true}
                    filter={this.state.filter}
                    onFilterChange={this.onFilterChange}
                    virtual={{
                        pageSize: pageSize,
                        skip: this.state.skip,
                        total: this.state.total
                    }}
                    onPageChange={this.pageChange}
                />
            </div>
        );
    }

    componentWillUnmount() {
        this.resetCach();
    }

    getCachedData(skip) {
        const data = [];
        for (let i = 0; i < pageSize; i++) {
            data.push(this.dataCaching[i + skip] || { ...emptyItem });
        }
        return data;
    }

    resetCach() {
        this.dataCaching.length = 0;
    }
}

ReactDOM.render(
    <AppComponent />,
    document.querySelector('my-app')
);
In this article