Work with Clipboard module
This functionality requires PRO version of the DHTMLX Grid (or DHTMLX Suite) package.
You can manage the clipboard functionality within a grid via the API of the Clipboard
module. It enables copying, cutting, and pasting data from a selected range of cells. Besides, it allows integrating with other grids or external applications like Google Spreadsheets.
Initializing the Clipboard module
To initialize the Clipboard
module, use the clipboard
property in the dhx.Grid component configuration. After the Grid component is created, the module is accessible through the grid.clipboard
property.
The module requires the RangeSelection
module to be enabled and is best used in conjunction with the BlockSelection
module in the "range"
mode (enabled on initialization of the Clipboard
module) for convenient range selection via the UI. Check the details below
const grid = new dhx.Grid("grid_container", {
columns: [
{ id: "a", header: [{ text: "A" }] },
{ id: "b", header: [{ text: "B" }] },
],
data: [
{ id: "1", a: "A1", b: "B1" },
{ id: "2", a: "A2", b: "B2" },
],
blockSelection: { mode: "range" }, // required for Clipboard to function (initializes automatically)
clipboard: true // enables the Clipboard module
});
Related sample: Grid. Clipboard with notifications (messages)
The clipboard
property can be set as an object to enable the module and define the modifier functions for data processing: copyModifier
, cutModifier
and pasteModifier
. Check the details below.
Using events of the Clipboard object
To make the process of working with clipboard more flexible, you can apply the related events of the clipboard
object:
afterCopy
, afterPaste
, beforeCopy
, beforePaste
, copyError
, pasteError
Interaction with cell selection
Automatic activation of BlockSelection module
When Clipboard
module is enabled (e.g., via grid.config.clipboard: true
), the BlockSelection
module is automatically activated in the range
mode unless another mode is specified.
Usage in other BlockSelection modes
If the BlockSelection
module is configured in the manual
mode, the Clipboard
module does not automatically receive a range. In this case, you should manually set the range using the RangeSelection
API. For this purpose, you need to call grid.range.setRange({ xStart, xEnd, yStart, yEnd })
.
Without a set range, copying and pasting will not work, as Clipboard API relies on data from the RangeSelection API.
Data source for Clipboard
The Clipboard API always uses data from the RangeSelection
API to determine the cells that will be copied or into which data will be pasted.
The cut
/paste
operations will be blocked in the grouping mode.
Interaction between Grids and external widgets
The Clipboard
module enables data exchange between multiple dhx.Grid
instances or with external applications like Google Spreadsheets, Microsoft Excel, or similar widgets. Data is copied to the clipboard in a text format with tab separators (\t
) between columns and newlines (\n
) between rows, matching the standard table format.
Related sample: Grid. Clipboard. Copy/сut/paste between grids with validation
Related sample: Grid. Clipboard between Grid and Spreadsheet
Integration with Google Spreadsheets
Data from a grid can be copied to the clipboard and pasted directly into Google Spreadsheets. Similarly, data from Google Spreadsheets can be copied and pasted into the grid. Use pasteModifier
to process data formats (e.g., converting strings to numbers).
Pasting from clipboard
Data from the clipboard is pasted into the range defined by rangeSelection
. The behavior depends on the size of the selected range and the number of copied elements:
-
If the range is smaller than the copied elements: all the copied elements will be pasted if there is enough space in the grid (i.e., the sufficient number of rows and columns exist beyond the range's starting point). For example, if 4 cells (2 rows x 2 columns) are copied and the range is set to 1 row x 2 columns, the data will be fully pasted, expanding the range to 2 rows, if rows are available.
-
If the range is larger than the copied elements: the copied elements will repeat cyclically to fill the entire range. For example, if 2 cells ("A1", "A2") are copied and the range contains 4 cells (2 rows x 2 columns), the result will be "A1", "A2", "A1", "A2".
The repetition of elements follows the order of copying, starting from the first cell.
Copying/pasting cells depending on the column type
Below you'll find the details on copying/pasting data depending on the type of a column.
Columns with type "date"
When copying cells with the column type type: "date"
, the formatted value is copied to the clipboard (not the original string or date object). For example, if the data contains "2025-04-11"
and the display format is set to "dd/mm/yyyy"
, the copied value will be "11/04/2025"
. This behavior simplifies working with dates in tables and other applications.
When pasting, values are validated after applying pasteModifier
(if defined). The value is checked for compliance with the column's dateFormat
(e.g., "dd/mm/yyyy"
) or whether it can be parsed as a valid Date
object (e.g., "2025-04-11"
or "April 11, 2025"
). If the value is valid, it is converted to the grid's expected format and inserted. If invalid (e.g., "abc"
or "31 12 2025"
), the paste operation is ignored, and the cell's current value remains unchanged.
Columns with type "number"
When copying cells with the column type type: "number"
, the values are copied to the clipboard as numbers, even if numberMask
or patternMask
is applied. For example, if a cell displays "1,234.56"
due to a mask, the copied value will be 1234.56
. This is done to maintain data purity and compatibility with other systems, such as spreadsheets or data processing software.
When pasting, values are validated after applying pasteModifier
(if defined). The value must be a valid number (e.g., 1234.56
or "1,234.56"
after cleaning). If the value is not a number (e.g., "abc"
), the paste operation is ignored, and the cell's current value remains unchanged.
Columns with type "string"
If patternMask
is applied to a cell (e.g., for formatting phone numbers or currency), the formatted value is copied to the clipboard.
For example, if the data contains "1234567890"
and the mask is "+# (###) ###-##-##"
, the copied value will be "+1 (234) 567-89-0"
. This preserves readability for the end user.
Templates
Templates applied to cell values (e.g., via the template
property) are not included in the data during copying. This prevents unwanted HTML or formatted text from entering the clipboard, which could disrupt the functionality of external widgets or tables (e.g., Google Spreadsheets). Only the "raw" value from the data is copied.
Columns with editors "combobox", "multiselect", "select"
If a column has editorType: "combobox"
, "multiselect"
, or "select"
, the value stored in the data (typically an id
or a key) is copied to the clipboard, not the displayed portion (e.g., the option text).
For example, if the data contains { id: "1", value: "Option 1" }
and the cell displays "Option 1"
, the copied value will be "1"
. This ensures data consistency when transferring between systems.
Using formatter functions
If you need a specific data format during copying or pasting, the default behavior can be modified using the formatter functions: copyModifier
, cutModifier
, pasteModifier
. Check the example below:
const grid = new dhx.Grid("grid_container", {
columns: [
{ id: "a", header: [{ text: "A" }] },
{ id: "b", header: [{ text: "B" }] },
],
data: [
{ id: "1", a: "A1", b: "B1" },
{ id: "2", a: "A2", b: "B2" },
],
clipboard: {
// adds a suffix based on the operation
copyModifier: (value, cell, cut) => `${value}${cut ? "-cut" : "-copied"}`,
cutModifier: (value, cell) => `${value}-removed`, // before cutting a value
pasteModifier: (value, cell) => value.replace("-copied", "") // removes the suffix on pasting
}
});
Related sample: Grid. Clipboard between two Grids with modifiers
These functions provide flexible control over how data is processed before copying, cutting, or pasting, which is particularly useful in the scenarios described below.
Why formatters are needed
- Format control: if the default behavior (e.g., copying numbers without a mask or
id
instead of text in acombobox
) does not meet the requirements, formatters allow data to be transformed into the desired form. - Compatibility: formatters help adapting data for specific external systems (e.g., preserving number masks or converting dates to a different format).
- Customization: you can add additional information (e.g., units of measurement) or remove unnecessary elements from the data.
- Preprocessing before validation:
pasteModifier
can preprocess data before it undergoes validation fordate
,number
, orboolean
types, ensuring compatibility with the grid's strict typing.
How to use formatters
copyModifier
- Applied before copying or cutting data to the clipboard. Allows overriding what is placed in the clipboard.
- Example: To copy the displayed text instead of the
id
for acombobox
, you can use the cell object (cell
) to retrieve the desired value.
cutModifier
- Applied before cutting to modify the data that goes into the clipboard and leave the original cells in a desired state (e.g., not fully clearing them).
- Example: You can add a suffix to the cut value to indicate its origin.
pasteModifier
- Applied before pasting data from the clipboard into cells. Allows transforming the incoming data into a format suitable for the grid, before validation for the
date
,number
, orboolean
types. - Example: If the clipboard contains a formatted date (
"11/04/2025"
) but the data requires"2025-04-11"
,pasteModifier
can perform this conversion.
- Applied before pasting data from the clipboard into cells. Allows transforming the incoming data into a format suitable for the grid, before validation for the
Examples
Copying numbers with a mask
This example demonstrates how to copy numbers while preserving the mask (e.g., "1,234.56"
instead of 1234.56
).
copyModifier: (value, cell, cut) => {
if (cell.column.type === "number" && cell.column.numberMask) {
return new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2
}).format(value);
}
return value;
}
Copying the displayed text of the Combobox option
This example shows how to copy the combobox option text ("Option 1"
) instead of the id
("1"
).
copyModifier: (value, cell, cut) => {
if (cell.column.editorType === "combobox") {
const options = cell.column.options;
const option = options.find(opt => opt.id === value);
return option ? option.value : value;
}
return value;
}
Pasting dates with validation
This example demonstrates how to transform a date from "11/04/2025"
to "2025-04-11"
during pasting and ensure it is valid.
pasteModifier: (value, cell) => {
if (cell.column.type === "date") {
const dateFormat = cell.column.dateFormat || "dd/mm/yyyy";
const regex = /^(\d{2})\/(\d{2})\/(\d{4})$/; // for dd/mm/yyyy
const match = value.match(regex);
if (match) {
const date = new Date(`${match[3]}-${match[2]}-${match[1]}`);
if (!isNaN(date.getTime())) {
return `${match[3]}-${match[2]}-${match[1]}`; // ISO format
}
}
return value; // validation will handle invalid cases
}
return value;
}
Removing patternMask
during copying
This example shows how to remove mask formatting (e.g., copy "1234567890"
instead of "+1 (234) 567-89-0"
).
copyModifier: (value, cell, cut) => {
if (cell.column.patternMask) {
return value.replace(/[^0-9]/g, ""); // remove all non-numeric characters
}
return value;
}
Related sample: Grid. Clipboard. Custom copy/cut/paste for number and date columns