Skip to content

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

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' },
],
},
}];