Dropdown Editor
The ColumnDropdown column type renders the Pro dropdown editor inside a grid cell. Use it for single-select values, or enable config.multiSelect when the cell value is an array.
Register ColumnDropdown in columnTypes, set columnType: 'dropdown' on a column, and provide a dropdown.source list with { value, label } options.
Source code
TypeScriptts
import { defineCustomElements } from '@revolist/revogrid/loader';
import type { ColumnRegular } from '@revolist/revogrid';
import { ColumnDropdown } from '@revolist/revogrid-pro';
import { currentTheme } from '../composables/useRandomData';
defineCustomElements();
const statusOptions = [
{ value: 'Open', label: 'Open' },
{ value: 'In Review', label: 'In Review' },
{ value: 'Complete', label: 'Complete' },
];
const tagOptions = [
{ value: 'Design', label: 'Design' },
{ value: 'Frontend', label: 'Frontend' },
{ value: 'Backend', label: 'Backend' },
{ value: 'QA', label: 'QA' },
];
const columns: ColumnRegular[] = [
{ prop: 'task', name: 'Task', size: 220 },
{
prop: 'status',
name: 'Status',
size: 180,
columnType: 'dropdown',
dropdown: {
source: statusOptions,
syncCellTemplate: true,
placeholder: 'Select status',
config: {
search: true,
},
},
},
{
prop: 'tags',
name: 'Tags',
size: 260,
columnType: 'dropdown',
dropdown: {
source: tagOptions,
syncCellTemplate: true,
placeholder: 'Select tags',
config: {
multiSelect: true,
search: true,
},
},
},
];
export function load(parentSelector: string) {
const grid = document.createElement('revo-grid');
const { isDark } = currentTheme();
grid.className = 'rounded-lg overflow-hidden cell-border';
grid.style.minHeight = '300px';
grid.range = true;
grid.theme = isDark() ? 'darkMaterial' : 'material';
grid.columnTypes = {
dropdown: ColumnDropdown,
};
grid.columns = columns;
grid.hideAttribution = true;
document.querySelector(parentSelector)?.appendChild(grid);
grid.source = [
{ task: 'Design filters', status: 'Open', tags: ['Design', 'Frontend'] },
{ task: 'Wire API payload', status: 'In Review', tags: ['Backend'] },
{ task: 'Regression pass', status: 'Complete', tags: ['QA', 'Frontend'] },
];
return () => grid.remove();
}
Vuevue
<template>
<RevoGrid
class="rounded-lg overflow-hidden cell-border"
range
:columns="columns"
:source="source"
:column-types="columnTypes"
:theme="isDark ? 'darkMaterial' : 'material'"
hide-attribution
style="min-height: 300px"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import RevoGrid from '@revolist/vue3-datagrid';
import type { ColumnRegular } from '@revolist/revogrid';
import { ColumnDropdown } from '@revolist/revogrid-pro';
import { currentThemeVue } from '../composables/useRandomData';
const { isDark } = currentThemeVue();
const source = ref([
{ task: 'Design filters', status: 'Open', tags: ['Design', 'Frontend'] },
{ task: 'Wire API payload', status: 'In Review', tags: ['Backend'] },
{ task: 'Regression pass', status: 'Complete', tags: ['QA', 'Frontend'] },
]);
const columnTypes = {
dropdown: ColumnDropdown,
};
const columns: ColumnRegular[] = [
{ prop: 'task', name: 'Task', size: 220 },
{
prop: 'status',
name: 'Status',
size: 180,
columnType: 'dropdown',
dropdown: {
syncCellTemplate: true,
source: [
{ value: 'Open', label: 'Open' },
{ value: 'In Review', label: 'In Review' },
{ value: 'Complete', label: 'Complete' },
],
placeholder: 'Select status',
config: {
search: true,
},
},
},
{
prop: 'tags',
name: 'Tags',
size: 260,
columnType: 'dropdown',
dropdown: {
syncCellTemplate: true,
source: [
{ value: 'Design', label: 'Design' },
{ value: 'Frontend', label: 'Frontend' },
{ value: 'Backend', label: 'Backend' },
{ value: 'QA', label: 'QA' },
],
placeholder: 'Select tags',
config: {
multiSelect: true,
search: true,
},
},
},
];
</script>
Reacttsx
import { useMemo } from 'react';
import { RevoGrid } from '@revolist/react-datagrid';
import type { ColumnRegular } from '@revolist/revogrid';
import { ColumnDropdown } from '@revolist/revogrid-pro';
import { currentTheme } from '../composables/useRandomData';
function EditorDropdown() {
const { isDark } = currentTheme();
const source = useMemo(
() => [
{ task: 'Design filters', status: 'Open', tags: ['Design', 'Frontend'] },
{ task: 'Wire API payload', status: 'In Review', tags: ['Backend'] },
{ task: 'Regression pass', status: 'Complete', tags: ['QA', 'Frontend'] },
],
[],
);
const columnTypes = useMemo(
() => ({
dropdown: ColumnDropdown,
}),
[],
);
const columns: ColumnRegular[] = useMemo(
() => [
{ prop: 'task', name: 'Task', size: 220 },
{
prop: 'status',
name: 'Status',
size: 180,
columnType: 'dropdown',
dropdown: {
syncCellTemplate: true,
source: [
{ value: 'Open', label: 'Open' },
{ value: 'In Review', label: 'In Review' },
{ value: 'Complete', label: 'Complete' },
],
placeholder: 'Select status',
config: {
search: true,
},
},
},
{
prop: 'tags',
name: 'Tags',
size: 260,
columnType: 'dropdown',
dropdown: {
syncCellTemplate: true,
source: [
{ value: 'Design', label: 'Design' },
{ value: 'Frontend', label: 'Frontend' },
{ value: 'Backend', label: 'Backend' },
{ value: 'QA', label: 'QA' },
],
placeholder: 'Select tags',
config: {
multiSelect: true,
search: true,
},
},
},
],
[],
);
return (
<RevoGrid
className="rounded-lg overflow-hidden cell-border"
range
source={source}
columns={columns}
columnTypes={columnTypes}
theme={isDark() ? 'darkMaterial' : 'material'}
hideAttribution
style={{ minHeight: '300px' }}
/>
);
}
export default EditorDropdown;
Angularts
import { Component, ViewEncapsulation } from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import { ColumnDropdown } from '@revolist/revogrid-pro';
import { currentTheme } from '../composables/useRandomData';
@Component({
selector: 'editor-dropdown-grid',
standalone: true,
imports: [RevoGrid],
template: `
<revo-grid
class="rounded-lg overflow-hidden cell-border"
[range]="true"
[source]="source"
[columns]="columns"
[columnTypes]="columnTypes"
[theme]="theme"
[hideAttribution]="true"
style="min-height: 300px;"
></revo-grid>
`,
encapsulation: ViewEncapsulation.None,
})
export class EditorDropdownGridComponent {
theme = currentTheme().isDark() ? 'darkMaterial' : 'material';
source = [
{ task: 'Design filters', status: 'Open', tags: ['Design', 'Frontend'] },
{ task: 'Wire API payload', status: 'In Review', tags: ['Backend'] },
{ task: 'Regression pass', status: 'Complete', tags: ['QA', 'Frontend'] },
];
columnTypes = {
dropdown: ColumnDropdown,
};
columns = [
{ prop: 'task', name: 'Task', size: 220 },
{
prop: 'status',
name: 'Status',
size: 180,
columnType: 'dropdown',
dropdown: {
syncCellTemplate: true,
source: [
{ value: 'Open', label: 'Open' },
{ value: 'In Review', label: 'In Review' },
{ value: 'Complete', label: 'Complete' },
],
placeholder: 'Select status',
config: {
search: true,
},
},
},
{
prop: 'tags',
name: 'Tags',
size: 260,
columnType: 'dropdown',
dropdown: {
syncCellTemplate: true,
source: [
{ value: 'Design', label: 'Design' },
{ value: 'Frontend', label: 'Frontend' },
{ value: 'Backend', label: 'Backend' },
{ value: 'QA', label: 'QA' },
],
placeholder: 'Select tags',
config: {
multiSelect: true,
search: true,
},
},
},
];
}
Features:
- Supports single-select cells with scalar values
- Supports multi-select cells with array values through
config.multiSelect: true - Can enable search with
config.search: true - Saves changes through RevoGrid cell edit events, so the grid data model stays in sync
- Supports custom option and selected-value templates through the dropdown render callbacks
- Can mirror the column cell template in options and selected values with
dropdown.syncCellTemplate
Keep cell and dropdown templates in sync
Section titled “Keep cell and dropdown templates in sync”Set dropdown.syncCellTemplate to true to reuse the column cellTemplate for both option rows and selected values. Object option fields are merged into the synthetic template model, so the same renderer can use metadata such as a status tone, avatar URL, or icon. Explicit renderOption and renderValue callbacks remain authoritative.
const columns = [{ prop: 'status', columnType: 'dropdown', cellTemplate: (h, { model, value }) => h('span', { class: `status-badge status-badge--${model.tone}`, }, model.label ?? value), dropdown: { syncCellTemplate: true, source: [ { value: 'active', label: 'Active', tone: 'green' }, { value: 'paused', label: 'Paused', tone: 'amber' }, ], },}];