Clipboard Plugin
The Clipboard plugin brings familiar copy/paste functionality to your grid with full keyboard shortcut support (Ctrl+C, Ctrl+V). It handles single cells, multi-cell selections, and integrates seamlessly with Excel and other spreadsheet applications via tab-delimited output.
Installation
Section titled “Installation”import '@toolbox-web/grid/features/clipboard';Basic Usage
Section titled “Basic Usage”Just enable the feature and you’re ready to go—keyboard shortcuts work automatically. Configure options like includeHeaders for copying column headers or delimiter for custom CSV formats.
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');grid.gridConfig = { columns: [ { field: 'name', header: 'Name' }, { field: 'email', header: 'Email' }, { field: 'department', header: 'Department' } ], features: { clipboard: { includeHeaders: true, quoteStrings: true, // Wrap text in quotes for CSV compatibility }, },};import '@toolbox-web/grid-react/features/selection';import '@toolbox-web/grid-react/features/clipboard';import { DataGrid } from '@toolbox-web/grid-react';
function MyGrid({ data }) { return ( <DataGrid rows={data} columns={[ { field: 'name', header: 'Name' }, { field: 'email', header: 'Email' }, { field: 'department', header: 'Department' } ]} selection="range" clipboard={{ includeHeaders: true, quoteStrings: true }} /> );}<script setup>import '@toolbox-web/grid-vue/features/selection';import '@toolbox-web/grid-vue/features/clipboard';import { TbwGrid, TbwGridColumn } from '@toolbox-web/grid-vue';
const data = [ { name: 'Alice', email: 'alice@example.com', department: 'Engineering' }, { name: 'Bob', email: 'bob@example.com', department: 'Marketing' },];</script>
<template> <TbwGrid :rows="data" selection="range" :clipboard="{ includeHeaders: true, quoteStrings: true }" > <TbwGridColumn field="name" header="Name" /> <TbwGridColumn field="email" header="Email" /> <TbwGridColumn field="department" header="Department" /> </TbwGrid></template>// Feature imports - enable the [selection] and [clipboard] inputsimport '@toolbox-web/grid-angular/features/selection';import '@toolbox-web/grid-angular/features/clipboard';
import { Component } from '@angular/core';import { Grid } from '@toolbox-web/grid-angular';import type { ColumnConfig } from '@toolbox-web/grid';
@Component({ selector: 'app-my-grid', imports: [Grid], template: ` <tbw-grid [rows]="rows" [columns]="columns" [selection]="'range'" [clipboard]="{ includeHeaders: true, quoteStrings: true }" style="height: 400px; display: block;"> </tbw-grid> `,})export class MyGridComponent { rows = [...];
columns: ColumnConfig[] = [ { field: 'name', header: 'Name' }, { field: 'email', header: 'Email' }, { field: 'department', header: 'Department' } ];}Default Clipboard
Section titled “Default Clipboard”<tbw-grid style="height: 350px;"></tbw-grid>import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/clipboard';import '@toolbox-web/grid/features/selection';
const sampleData = [ { id: 1, name: 'Alice', email: 'alice@example.com', department: 'Engineering' }, { id: 2, name: 'Bob', email: 'bob@example.com', department: 'Marketing' }, { id: 3, name: 'Carol', email: 'carol@example.com', department: 'Engineering' }, { id: 4, name: 'Dan', email: 'dan@example.com', department: 'Sales' },];const columns = [ { field: 'id', header: 'ID', type: 'number' }, { field: 'name', header: 'Name' }, { field: 'email', header: 'Email' }, { field: 'department', header: 'Department' },];
const grid = queryGrid('tbw-grid')!;
function rebuild(includeHeaders = false, quoteStrings = false) { grid.gridConfig = { columns, features: { selection: 'range', clipboard: { includeHeaders, quoteStrings }, }, }; grid.rows = sampleData;}
rebuild();Select cells and use Ctrl+C to copy, Ctrl+V to paste.
Copy & Paste (Auto-Paste)
Section titled “Copy & Paste (Auto-Paste)”Or paste tab/comma-separated data from Excel or Sheets!
Also try to select an area to paste in. Pasting will be restricted to that area only.
import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/clipboard';import '@toolbox-web/grid/features/editing';import '@toolbox-web/grid/features/selection';
const grid = queryGrid('tbw-grid');
grid.gridConfig = { columns: [ { field: 'col1', header: 'Column 1', editable: true }, { field: 'col2', header: 'Column 2', editable: true }, { field: 'col3', header: 'Column 3', editable: true }, ], features: { selection: 'range', clipboard: true, editing: true, },};
grid.rows = [ { col1: 'A1', col2: 'B1', col3: 'C1' }, { col1: 'A2', col2: 'B2', col3: 'C2' }, { col1: 'A3', col2: 'B3', col3: 'C3' }, { col1: 'A4', col2: 'B4', col3: 'C4' },];<div class="sample-data-box" title="Select this text and Ctrl+C to copy, then paste into the grid below" style="padding: 12px; background: var(--sl-color-gray-6); border-bottom: 1px solid var(--sl-color-gray-5); font-family: monospace; font-size: 13px; white-space: pre; user-select: all; cursor: text;">X1	Y1	Z1X2	Y2	Z2</div> <div style="padding: 12px; background: var(--sl-color-gray-6); border-bottom: 1px solid var(--sl-color-gray-5); font-size: 14px; color: var(--sl-color-gray-2);"> <strong>Try it:</strong> Select the sample data above → Ctrl+C → Click a cell in the grid → Ctrl+V to paste. <br>Or paste tab/comma-separated data from Excel or Sheets! <br>Also try to select an area to paste in. Pasting will be restricted to that area only. </div> <tbw-grid style="height: 350px;"></tbw-grid>By default, the ClipboardPlugin handles paste operations automatically—no event handling needed. Just add the plugin and paste works out of the box.
Custom Paste Handler
Section titled “Custom Paste Handler”<tbw-grid style="height: 350px;"></tbw-grid>import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/clipboard';import '@toolbox-web/grid/features/selection';
// Sample data for clipboard demosconst sampleData = [ { id: 1, name: 'Alice', email: 'alice@example.com', department: 'Engineering' }, { id: 2, name: 'Bob', email: 'bob@example.com', department: 'Marketing' }, { id: 3, name: 'Carol', email: 'carol@example.com', department: 'Engineering' }, { id: 4, name: 'Dan', email: 'dan@example.com', department: 'Sales' },];const columns = [ { field: 'id', header: 'ID', type: 'number' }, { field: 'name', header: 'Name' }, { field: 'email', header: 'Email' }, { field: 'department', header: 'Department' },];
// Sample data to copy const sampleDataBox = document.createElement('div'); sampleDataBox.style.cssText = ` padding: 12px; background: var(--demo-sample-bg); border-bottom: 1px solid var(--demo-sample-border); font-family: monospace; font-size: 13px; white-space: pre; user-select: all; cursor: text; `; sampleDataBox.textContent = `hello\tworldfoo\tbar`; sampleDataBox.title = 'Paste this into the grid - values will be uppercased!';
// Instructions banner const banner = document.createElement('div'); banner.style.cssText = ` padding: 12px; background: var(--demo-info-bg); border-bottom: 1px solid var(--demo-info-border); font-size: 14px; color: var(--demo-info-fg); `; banner.innerHTML = ` <strong>Custom Handler:</strong> Pasted values are automatically UPPERCASED. <br>This demo also prevents adding new rows when pasting beyond the grid. `;
// Grid const grid = queryGrid('tbw-grid'); grid.style.cssText = 'flex: 1;';
// Custom paste handler that uppercases values and prevents adding rows const customPasteHandler = (detail, gridEl) => { if (!detail.target) return;
const { rows: pastedRows, target, fields } = detail; const columns = gridEl.effectiveConfig.columns ?? []; const allFields = columns.map((c) => c.field); const currentRows = [...(gridEl.rows[])];
pastedRows.forEach((rowData, rowOffset) => { const targetRowIndex = target.row + rowOffset;
// This handler allows adding rows (unlike the code sample which doesn't) while (targetRowIndex >= currentRows.length) { const emptyRow = {}; allFields.forEach((f) => (emptyRow[f] = '')); currentRows.push(emptyRow); }
currentRows[targetRowIndex] = { ...currentRows[targetRowIndex] }; rowData.forEach((value, colOffset) => { const field = fields[colOffset]; if (field) { // Transform: uppercase all values currentRows[targetRowIndex][field] = value.toUpperCase(); } }); });
gridEl.rows = currentRows; };
grid.gridConfig = { columns: [ { field: 'col1', header: 'Column 1' }, { field: 'col2', header: 'Column 2' }, { field: 'col3', header: 'Column 3' }, ], features: { selection: 'range', clipboard: { pasteHandler: customPasteHandler }, }, };
grid.rows = [ { col1: 'A1', col2: 'B1', col3: 'C1' }, { col1: 'A2', col2: 'B2', col3: 'C2' }, { col1: 'A3', col2: 'B3', col3: 'C3' }, ];For advanced use cases, provide a custom pasteHandler to validate, transform, or integrate with state management.
Single Cell Mode
Section titled “Single Cell Mode”Click a cell and press Ctrl+C to copy its value. No range selection — only the focused cell is copied.
import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/clipboard';
const grid = queryGrid('tbw-grid');
grid.gridConfig = { columns: [ { field: 'id', header: 'ID', type: 'number', width: 60 }, { field: 'name', header: 'Name' }, { field: 'department', header: 'Department' }, { field: 'email', header: 'Email' }, { field: 'salary', header: 'Salary', type: 'number', align: 'right' }, ], features: { clipboard: true },};
grid.rows = [ { id: 1, name: 'Alice Johnson', department: 'Engineering', email: 'alice@company.com', salary: 85000 }, { id: 2, name: 'Bob Smith', department: 'Marketing', email: 'bob@company.com', salary: 72000 }, { id: 3, name: 'Carol Williams', department: 'Engineering', email: 'carol@company.com', salary: 92000 }, { id: 4, name: 'David Brown', department: 'Sales', email: 'david@company.com', salary: 68000 }, { id: 5, name: 'Emma Davis', department: 'HR', email: 'emma@company.com', salary: 65000 }, { id: 6, name: 'Frank Miller', department: 'Engineering', email: 'frank@company.com', salary: 88000 },];<p class="demo-hint" style="margin: 0; padding: 8px 12px; font-size: 0.85rem; color: var(--sl-color-gray-3);"> Click a cell and press <kbd>Ctrl+C</kbd> to copy its value. No range selection — only the focused cell is copied.</p><tbw-grid style="height: 350px;"></tbw-grid>Without a SelectionPlugin, the clipboard operates on a single focused cell — press Ctrl+C to copy just that cell’s value.
Configuration Options
Section titled “Configuration Options”| Option | Type | Default | Description |
|---|---|---|---|
includeHeaders | boolean | false | Include column headers in copied data |
delimiter | string | '\t' | Column delimiter (tab for Excel compatibility) |
newline | string | '\n' | Row delimiter |
quoteStrings | boolean | false | Wrap string values in quotes |
processCell | (value, field, row) => string | - | Custom cell value processor for copy operations |
pasteHandler | PasteHandler | null | defaultPasteHandler | Custom paste handler. Set to null to disable auto-paste and handle the paste event manually |
Paste Behavior
Section titled “Paste Behavior”The clipboard plugin respects both selection bounds and the editable column property when pasting:
Editable Columns
Section titled “Editable Columns”Paste only works on columns marked editable: true. Non-editable columns are skipped during paste, preserving column alignment:
columns: [ { field: 'id', header: 'ID' }, // NOT editable - paste skipped { field: 'name', header: 'Name', editable: true }, // Paste allowed { field: 'email', header: 'Email', editable: true }, // Paste allowed]If you paste "1\t2\t3" into this grid, only the name and email columns receive values (2 and 3). The id column remains unchanged.
Selection Bounds
Section titled “Selection Bounds”| Selection Type | Paste Behavior |
|---|---|
| Single cell | Paste expands freely from that cell, adding rows if needed |
| Range selection | Paste is clipped to fit within the selected range |
| Row selection | Paste is clipped to the selected rows (all columns within those rows) |
| No selection | Paste starts at row 0, column 0 |
Example: If you have a 2×2 range selected and paste 3×3 data, only the 2×2 portion that fits will be applied.
Keyboard Shortcuts
Section titled “Keyboard Shortcuts”| Shortcut | Action |
|---|---|
Ctrl+C / Cmd+C | Copy selected cells |
Ctrl+V / Cmd+V | Paste into selected cells |
Programmatic API
Section titled “Programmatic API”The ClipboardPlugin exposes methods for programmatic copy operations with fine-grained control over which columns and rows to include. This is ideal for workflows where users select rows in the grid, then choose columns via a dialog before copying.
Basic Copy
Section titled “Basic Copy”const plugin = grid.getPluginByName('clipboard');
// Copy current selection to clipboardawait plugin.copy();
// Copy with headers includedawait plugin.copy({ includeHeaders: true });Copy with Column/Row Control (CopyOptions)
Section titled “Copy with Column/Row Control (CopyOptions)”The copy() method accepts CopyOptions to precisely control what gets copied—independently of the current selection:
const plugin = grid.getPluginByName('clipboard');
// Copy specific columns from specific rowsawait plugin.copy({ rowIndices: [0, 3, 7], // Non-contiguous rows supported columns: ['name', 'email'], // Only these columns includeHeaders: true,});
// Copy specific rows with all visible columnsawait plugin.copyRows([0, 5]);
// Copy specific rows with column filterawait plugin.copyRows([0, 5], { columns: ['name', 'department'] });Preview Without Copying
Section titled “Preview Without Copying”Use getSelectionAsText() to get the formatted text without writing to the clipboard—useful for preview dialogs:
const text = plugin.getSelectionAsText({ columns: ['name', 'email', 'department'], includeHeaders: true,});// "Name\tEmail\tDepartment\nAlice\talice@example.com\tEngineering\n..."CopyOptions Reference
Section titled “CopyOptions Reference”| Option | Type | Default | Description |
|---|---|---|---|
columns | string[] | - | Specific column fields to include |
rowIndices | number[] | - | Specific row indices to copy (non-contiguous OK) |
includeHeaders | boolean | config value | Include column headers in copied text |
delimiter | string | config value | Column delimiter override |
newline | string | config value | Row delimiter override |
processCell | (value, field, row) => string | config value | Custom cell value processor for this operation |
// Paste from clipboardawait plugin.paste();
// Get last copied infoconst lastCopied = plugin.getLastCopied();// { text: '...', timestamp: 1234567890 }Excel Compatibility
Section titled “Excel Compatibility”The default tab delimiter ensures copied data pastes correctly into Excel:
features: { clipboard: { delimiter: '\t', // Tab for Excel includeHeaders: true, // Include column names },},Events
Section titled “Events”Select cells and use Ctrl+C / Ctrl+V to copy and paste.
| Event | Detail | Description |
|---|---|---|
copy | { text, rowCount, columnCount } | Fired after cells are copied |
paste | { rows, text, target, fields } | Fired after data is pasted |
Styling
Section titled “Styling”The clipboard plugin doesn’t add visible UI elements. Selection styling is handled by the SelectionPlugin.