Assignee Editor
Double-click an Assignees cell to open the resource picker. Selected people appear as removable tags above a searchable RevoGrid with checkboxes and allocation units. This example includes 5,000 people; the picker virtualizes its rows.
Source code
import type { ColumnRegular } from '@revolist/revogrid';import { type AssigneeDropdownOption } from '@revolist/revogrid-pro';
const people = [ { id: 'jordan', name: 'Jordan Diaz', role: 'Automation Engineer' }, { id: 'nina', name: 'Nina Kim', role: 'Platform Engineer' }, { id: 'ravi', name: 'Ravi Patel', role: 'QA Lead' }, { id: 'sam', name: 'Sam Rivera', role: 'Product Owner' }, { id: 'vera', name: 'Vera Khan', role: 'Security Engineer' },];const options: AssigneeDropdownOption[] = people.map(person => ({ value: person.id, label: `${person.name} - ${person.role}`, name: person.name, role: person.role,}));
for (let i = options.length; i < 5000; i++) { options.push({ value: `person-${i}`, label: `Team member ${i}`, name: `Team member ${i}`, role: 'Engineer' });}
export function createRows() { return [ { task: 'Automate regression tests', assignees: [{ value: 'jordan', units: 100 }, { value: 'ravi', units: 50 }] }, { task: 'Review platform design', assignees: [{ value: 'nina', units: 100 }] }, { task: 'Plan the next release', assignees: [{ value: 'sam', units: 75 }, { value: 'vera', units: 25 }] }, { task: 'Assign a new task', assignees: [] }, ];}
export function createColumns(): ColumnRegular[] { return [ { prop: 'task', name: 'Task', size: 260 }, { prop: 'assignees', name: 'Assignees', size: 380, columnType: 'assignee', assigneeEditor: { source: options }, }, ];}import { defineCustomElements } from '@revolist/revogrid/loader';import { ColumnAssignee } from '@revolist/revogrid-pro';import { currentTheme } from '../composables/useRandomData';import { createColumns, createRows } from './assignee-data';defineCustomElements();export function load(parentSelector: string, rows = createRows()) { const grid = document.createElement('revo-grid'); grid.theme = currentTheme().isDark() ? 'darkMaterial' : 'material'; grid.columnTypes = { assignee: ColumnAssignee }; grid.columns = createColumns(); grid.hideAttribution = true; grid.style.height = '300px'; document.querySelector(parentSelector)?.appendChild(grid); grid.source = rows; return () => grid.remove();}<template> <RevoGrid :columns="columns" :source="source" :column-types="columnTypes" :theme="isDark ? 'darkMaterial' : 'material'" hide-attribution style="height: 300px" /></template><script setup lang="ts">import { ref } from 'vue';import RevoGrid from '@revolist/vue3-datagrid';import { ColumnAssignee } from '@revolist/revogrid-pro';import { currentThemeVue } from '../composables/useRandomData';import { createColumns, createRows } from './assignee-data';const { isDark } = currentThemeVue();const source = ref(createRows());const columns = createColumns();const columnTypes = { assignee: ColumnAssignee };</script>import { useMemo } from 'react';import { RevoGrid } from '@revolist/react-datagrid';import { ColumnAssignee } from '@revolist/revogrid-pro';import { currentTheme } from '../composables/useRandomData';import { createColumns, createRows } from './assignee-data';export default function EditorAssignee({ rows }: { rows?: any[] }) { const source = useMemo(() => rows?.length ? rows : createRows(), [rows]); const columns = useMemo(createColumns, []); const columnTypes = useMemo(() => ({ assignee: ColumnAssignee }), []); return <RevoGrid source={source} columns={columns} columnTypes={columnTypes} theme={currentTheme().isDark() ? 'darkMaterial' : 'material'} hideAttribution style={{ height: '300px' }} />;}import { Component, ViewEncapsulation } from '@angular/core';import { RevoGrid } from '@revolist/angular-datagrid';import { ColumnAssignee } from '@revolist/revogrid-pro';import { currentTheme } from '../composables/useRandomData';import { createColumns, createRows } from './assignee-data';@Component({ selector: 'editor-assignee-grid', standalone: true, imports: [RevoGrid], template: `<revo-grid [source]="source" [columns]="columns" [columnTypes]="columnTypes" [theme]="theme" [hideAttribution]="true" style="height: 300px"></revo-grid>`, encapsulation: ViewEncapsulation.None,})export class EditorAssigneeGridComponent { source = createRows(); columns = createColumns(); columnTypes = { assignee: ColumnAssignee }; theme = currentTheme().isDark() ? 'darkMaterial' : 'material';}Configuration
Section titled “Configuration”Register the Pro column type and supply resources with stable IDs:
import { ColumnAssignee } from '@revolist/revogrid-pro';import '@revolist/revogrid-pro/styles.css';
grid.columnTypes = { assignee: ColumnAssignee };grid.columns = [{ prop: 'assignees', name: 'Assignees', size: 380, columnType: 'assignee', assigneeEditor: { source: [ { value: 'celia', label: 'Celia', name: 'Celia', role: 'Engineer' }, { value: 'dan', label: 'Dan', name: 'Dan', role: 'Designer' }, ], defaultUnits: 100, showAvatars: true, },}];grid.source = [{ assignees: [{ value: 'celia', units: 100 }] }];Each cell stores AssigneeAssignment[]: { value: string | number, units: number }. Units are percentages and default to 100 for newly selected people. Zero and values over 100 are supported; tags omit the percentage when units are zero; blank, negative, and non-finite values block Save. Resource IDs distinguish numbers from strings and remain stable when a person is renamed.
Search, selection, and saving
Section titled “Search, selection, and saving”Search by name or role. Checkbox selection uses Pro’s SelectionPlugin inside the nested RevoGrid. Search hides rows without dropping their assignments. Edit Units for a selected person or remove their tag above the picker.
Save commits the draft through the grid’s normal editing lifecycle. Cancel, Escape, clicking outside, or scrolling the parent grid discards it. Grid and column read-only settings prevent editing. Resource options accept disabled: true to lock their selection and allocation. Existing IDs missing from the source remain visible as tags and are preserved until explicitly removed.
Resources support { value, label, name?, role?, avatarUrl?, initials?, color?, disabled? }. Badges and picker rows show avatars by default. Supply avatarUrl on a resource to show its image; resources without an image use generated initials/colors. Set assigneeEditor.showAvatars: false to hide avatars in both saved badges and the editor, including picker rows. Include Pro styles for the shared dropdown, tags, controls, and picker.
The editor requires Pro only. It does not require Gantt or change Gantt assignments. For simple ID-array dropdowns without allocation units, the existing createAssigneeDropdown and ColumnDropdown remain available; see Dropdown Editor.