{"id":14088,"date":"2025-07-15T11:11:53","date_gmt":"2025-07-15T08:11:53","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=14088"},"modified":"2026-10-22T01:08:34","modified_gmt":"2026-10-21T22:08:34","slug":"dhtmlx-suite-9-2","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/dhtmlx-suite-9-2\/","title":{"rendered":"DHTMLX Suite 9.2: Grid with History Management, Spreadsheet-Like Interactions, Improved Drag-and-Drop, and More"},"content":{"rendered":"<p>We are thrilled to present a new update to our <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxSuite\/\" rel=\"noopener\" target=\"_blank\">JavaScript UI widgets library<\/a>, bringing the Suite&#8217;s Grid widget to a new level. While nominally it is a minor release, it introduces a range of API modules that will enable developers to configure more interactive and user-friendly data tables with spreadsheet-like capabilities. To be specific, this update enriches our <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGrid\/\" rel=\"noopener\" target=\"_blank\">JavaScript Grid<\/a> with history management, clipboard operations, advanced data selection, and new range selection options. These new API modules come with advanced settings. Moreover, you&#8217;ll certainly enjoy seeing significant enhancements in drag-and-drop functionality, a new approach to exporting Grid data to Excel, updated integration samples with top JavaScript frameworks, and more.<\/p>\n\n\t\t<div class='post-banner'>\n\t\t    <div class='post-banner__inside'>\n\t\t        <div>\n\t\t            <div class=\"post-banner__title\">Download DHTMLX Suite v9.2<\/div>\n\t\t            <div class=\"post-banner__text\">Estimate the updated functionality for building modern data-intensive apps<\/div>\n                <\/div>\n\t\t            \n                \n            <div class='post-banner__btn'>\n                <a href='https:\/\/dhtmlx.com\/docs\/products\/dhtmlxSuite\/download.shtml' title='' class='button-secondary'>Get free trial<\/a>\n            <\/div>\n        \n            <\/div>\n\t\t<\/div>\n\t\n<p>Get ready to meet the new Suite 9.2 with features that are typically reserved for major version jumps!<\/p>\n<h5>History Module (PRO)<\/h5>\n<p>Data editing is an integral part of working with JavaScript data tables, where errors or accidental changes are not rare. To ensure greater control over recent grid interactions, DHTMLX Grid v9.2 introduces the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_history\/\" rel=\"noopener\" target=\"_blank\">History module<\/a>. It is designed to automatically track user actions via the UI (like cell edits, structural changes, content clearing, etc.) and temporarily store them, thereby maintaining a reliable record of changes within the grid. Also, the module allows adding <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_history\/#applying-undoredo-operations-to-grid-history-actions\" rel=\"noopener\" target=\"_blank\">undo\/redo<\/a> capabilities for reverting to previous states or repeating actions using the corresponding operations.<\/p>\n<p>To enable this functionality, you should activate the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/grid_history_config\/\" rel=\"noopener\" target=\"_blank\">history<\/a><\/strong> property in the Grid configuration. This property includes the <strong>limit<\/strong> parameter aimed at specifying the number of actions to be recorded in the grid table history. <\/p>\n<p>For instance, the data table configuration below includes the history module with a limit of 10 actions:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> grid <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">Grid<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;grid&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; columns<span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; data<span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; clipboard<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; history<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; limit<span class=\"sy0\">:<\/span> <span class=\"nu0\">10<\/span><span class=\"sy0\">,<\/span><span class=\"co1\">\/\/ Limits the history to 10 actions<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; editable<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; autoWidth<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; autoHeight<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>To show you how the <strong>limit<\/strong> parameter works in action, we set its value to 3 in the example below:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/ezgif.com-speed-1.gif\" alt=\"Undo\/Redo - limit parameter\" width=\"1012\" height=\"748\" class=\"aligncenter size-full wp-image-14109\" \/>          <a href=\"https:\/\/snippet.dhtmlx.com\/vznpyeit?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>The <a href=\"https:\/\/docs.dhtmlx.com\/suite\/category\/history-api\/\" rel=\"noopener\" target=\"_blank\">rich API<\/a> of the History module offers a range of methods and events for managing the history of actions within the Grid component, including adding, removing, or clearing table rows, as well as editing individual (or multiple) cells. <\/p>\n<p>Undo and redo operations are applied to Grid history actions using the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/history\/undo_method\/\" rel=\"noopener\" target=\"_blank\">undo()<\/a><\/strong> and <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/history\/redo_method\/\" rel=\"noopener\" target=\"_blank\">redo()<\/a><\/strong> methods, respectively. This functionality is quite flexible thanks to the availability of related events in the history config, such as <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/history\/beforeundo_event\/\" rel=\"noopener\" target=\"_blank\">beforeUndo<\/a><\/strong>, <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/history\/afterundo_event\/\" rel=\"noopener\" target=\"_blank\">afterUndo<\/a><\/strong>, <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/history\/beforeredo_event\/\" rel=\"noopener\" target=\"_blank\">beforeRedo<\/a><\/strong>, and <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/history\/afterredo_event\/\" rel=\"noopener\" target=\"_blank\">afterRedo<\/a><\/strong>.<\/p>\n<p>Overall, the History module ensures a smoother and safer editing experience, especially in large or collaborative data tables.<\/p>\n<h5>RangeSelection Module (PRO)<\/h5>\n<p>The new <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/configuration\/#managing-range-selection-in-grid\" rel=\"noopener\" target=\"_blank\">RangeSelection<\/a> module may seem like a small feature, but it is a crucial part of the new Grid functionalities for effective data management. The module offers the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/category\/rangeselection-api\/\" rel=\"noopener\" target=\"_blank\">API<\/a> for intuitive management of range selection, which is essential for selecting and handling multiple cells in the grid table.<\/p>\n<p>In the Grid configuration, you can specify this feature using the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/grid_rangeselection_config\/\" rel=\"noopener\" target=\"_blank\">rangeSelection<\/a><\/strong> property as a boolean or as an object to fine-tune its behavior.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">rangeSelection<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span> <span class=\"co1\">\/\/ enables the RangeSelection module<\/span><\/div><\/div>\n<p>Regarding <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_rangeselection\/\" rel=\"noopener\" target=\"_blank\">additional configuration options<\/a> for the RangeSelection module, we can point out the following capabilities:<\/p>\n<ul>\n<li>Setting range selection via the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/setrange_method\/\" rel=\"noopener\" target=\"_blank\">setRange()<\/a><\/strong> method:<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> grid <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">Grid<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;grid_container&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ other configuration<\/span><br \/>\n&nbsp; &nbsp; columns<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;b&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; data<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span><span class=\"sy0\">,<\/span> a<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A1&quot;<\/span><span class=\"sy0\">,<\/span> b<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;2&quot;<\/span><span class=\"sy0\">,<\/span> a<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A2&quot;<\/span><span class=\"sy0\">,<\/span> b<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B2&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; rangeSelection<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\ngrid.<span class=\"me1\">range<\/span>.<span class=\"me1\">setRange<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> xStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> yStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>The method includes the <strong>range<\/strong> parameter for defining a selection range with start and end coordinates for columns and rows. <\/p>\n<p>You can choose to merge the new range with the existing one using the method&#8217;s <strong>join<\/strong> parameter:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">...<br \/>\n<span class=\"me1\">grid<\/span>.<span class=\"me1\">range<\/span>.<span class=\"me1\">setRange<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> xStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> yStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\ngrid.<span class=\"me1\">range<\/span>.<span class=\"me1\">setRange<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> xEnd<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;b&quot;<\/span><span class=\"sy0\">,<\/span> yEnd<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;2&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw2\">true<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ merges with the current range<\/span><\/div><\/div>\n<p>If some coordinates are omitted, they are automatically filled in:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">...<br \/>\n<span class=\"me1\">grid<\/span>.<span class=\"me1\">range<\/span>.<span class=\"me1\">setRange<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> xStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> yStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ ending coordinates are not specified<\/span><\/div><\/div>\n<p><strong>Note:<\/strong> <em>the starting ID for at least one coordinate is required!<\/em><\/p>\n<ul>\n<li>Resetting range selection via the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/resetrange_method\/\" rel=\"noopener\" target=\"_blank\">resetRange()<\/a><\/strong> method:<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">...<br \/>\n<span class=\"me1\">grid<\/span>.<span class=\"me1\">range<\/span>.<span class=\"me1\">setRange<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> xStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> yStart<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\ngrid.<span class=\"me1\">range<\/span>.<span class=\"me1\">resetRange<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Both <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/setrange_method\/\" rel=\"noopener\" target=\"_blank\">setRange()<\/a><\/strong> and <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/resetrange_method\/\" rel=\"noopener\" target=\"_blank\">resetRange()<\/a><\/strong> methods come with related events for a more flexible configuration. <\/p>\n<p>Apart from that, there are methods of the <strong>range<\/strong> object for getting the current range selection (<strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/getrange_method\/\" rel=\"noopener\" target=\"_blank\">getRange()<\/a><\/strong>), checking the module state (<strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/isdisabled_method\/\" rel=\"noopener\" target=\"_blank\">isDisabled()<\/a><\/strong>), determining whether a cell is in the range (<strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/rangeselection\/isranged_method\/\" rel=\"noopener\" target=\"_blank\">isRanged()<\/a><\/strong>), and more.<\/p>\n<p>While RangeSelection is technically a separate module, it lays the foundation for two more new modules of the Grid component, which we&#8217;ll consider below.<\/p>\n<h5>BlockSelection Module (PRO)<\/h5>\n<p>The updated DHTMLX Grid also features the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/configuration\/#managing-block-selection-in-grid\" rel=\"noopener\" target=\"_blank\">BlockSelection<\/a> module, which allows for selecting multiple adjacent cells using the mouse, touch gestures, or keyboard combinations, similar to Excel or Google Sheets.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/ezgif.com-added-text-1.gif\" alt=\"BlockSelection - cell selection\" width=\"1148\" height=\"684\" class=\"aligncenter size-full wp-image-14116\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/42fp5qvt?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>As in the example above, cell blocks can be selected by clicking and dragging over the required grid area or by using the &#8220;Shift+click&#8221; combination. <\/p>\n<p>For those who are familiar with keyboard navigation for selecting and managing ranges in Google Sheets, our Grid offers a similar approach for selecting cell blocks in data tables with <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_blockselection\/#keyboard-navigation\" rel=\"noopener\" target=\"_blank\">keyboard and mouse combinations<\/a>.<\/p>\n<p>To make the BlockSelection work in your JavaScript data table, you need to add the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/grid_blockselection_config\/\" rel=\"noopener\" target=\"_blank\">blockSelection<\/a><\/strong> property in the Grid configuration. Similar to the RangeSelection module, it can be set as a simple boolean value or as an object to unlock additional configuration options. <\/p>\n<p>One of such extra options is called a selection handle, appearing in the bottom-right corner of the selected range after being enabled via <strong>blockSelection.handle<\/strong>. By default, it ensures that the data from pre-selected cells will be sequentially inserted into the range determined with the handle by dragging.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/ezgif.com-speed-2.gif\" alt=\"BlockSelection - selection handle\" width=\"1016\" height=\"564\" class=\"aligncenter size-full wp-image-14112\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/42fp5qvt?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>It is possible to override the default selection handle behavior using the handler function. In the example below, you can see that the use of the selection handle leads to the generation of new values in the selected area in accordance with the specified logic:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image1.gif\" alt=\"Data selection with custom handle\" width=\"1020\" height=\"604\" class=\"aligncenter size-full wp-image-14095\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/sryiguxu?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>The behavior of the BlockSelection module in <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_blockselection\/#cell-selection\" rel=\"noopener\" target=\"_blank\">cell selection<\/a>, <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_blockselection\/#selection-handle\" rel=\"noopener\" target=\"_blank\">selection handle<\/a>, and <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_blockselection\/#interaction-with-other-modules\" rel=\"noopener\" target=\"_blank\">with other modules<\/a> depends on the configured mode. For instance, cell selection in the range mode relies on the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/category\/rangeselection-api\/\" rel=\"noopener\" target=\"_blank\">RangeSelection API<\/a>, while the manual mode implies the use of custom event-based logic.<\/p>\n<p>Also, you can change the styling of BlockSelection using CSS like in the example below:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image3.png\" alt=\"BlockSelection module - custom styling with CSS\" width=\"1051\" height=\"444\" class=\"aligncenter size-full wp-image-14096\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image3.png 1051w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image3-300x127.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image3-768x324.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image3-1024x433.png 1024w\" sizes=\"auto, (max-width: 1051px) 100vw, 1051px\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/4k3x4bfm?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>For more details on BlockSelection setup and customization, check out the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_blockselection\/\" rel=\"noopener\" target=\"_blank\">configuration guide<\/a>.<\/p>\n<p>This module is another important addition to the Grid API that sets the stage for the next major functionality of this release.<\/p>\n<h5>Clipboard Module (PRO)<\/h5>\n<p>The DHTMLX Suite 9.2 brings in spreadsheet-like usability into grid-based interfaces with the new <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/configuration\/#clipboard\" rel=\"noopener\" target=\"_blank\">Clipboard<\/a> module. Fueled by data from the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/category\/rangeselection-api\/\" rel=\"noopener\" target=\"_blank\">RangeSelection API<\/a> and the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/configuration\/#managing-block-selection-in-grid\" rel=\"noopener\" target=\"_blank\">BlockSelection<\/a> module (automatically enabled during Clipboard initialization), it allows end users to easily copy, cut, and paste data from a selected range of cells within a table. These actions can also be performed between multiple grid instances or with external tools such as Microsoft Excel and Google Sheets.<\/p>\n<p>To activate the clipboard support in the Grid configuration, you need the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/grid_clipboard_config\/\" rel=\"noopener\" target=\"_blank\">clipboard<\/a><\/strong> property that can be used in two ways:<\/p>\n<ul>\n<li><strong>as a boolean value to enable the Clipboard module with the default behavior<\/strong><\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> grid <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">Grid<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;grid_container&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; columns<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;b&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; data<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span><span class=\"sy0\">,<\/span> a<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A1&quot;<\/span><span class=\"sy0\">,<\/span> b<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;2&quot;<\/span><span class=\"sy0\">,<\/span> a<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A2&quot;<\/span><span class=\"sy0\">,<\/span> b<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B2&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; blockSelection<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> mode<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;range&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"co1\">\/\/ required for Clipboard to function (initializes automatically)<\/span><br \/>\n&nbsp; &nbsp; clipboard<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span> <span class=\"co1\">\/\/ enables the Clipboard module<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image7.gif\" alt=\"clipboard operations\" width=\"988\" height=\"396\" class=\"aligncenter size-full wp-image-14098\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/2nar7ocd?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>As you can see from the example above, clipboard operations are accompanied by helpful messages clarifying when any of the clipboard operations take place. These clarifications are generated with the help of events included in the Clipboard module, which are listened to via the <strong>grid.clipboard<\/strong> object.<\/p>\n<ul>\n<li><strong>as an object for <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_clipboard\/\" rel=\"noopener\" target=\"_blank\">advanced clipboard settings<\/a><\/strong><\/li>\n<\/ul>\n<p>Complex data tables often come with various column types (date, number, editors, etc.); therefore, the Clipboard module requires extended settings for processing clipboard operations in tables with particular column types properly. If your project has specific requirements for data formatting during clipboard operations, you can benefit from new <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_clipboard\/#using-formatter-functions\" rel=\"noopener\" target=\"_blank\">formatter functions<\/a> (or simply formatters) such as <strong>copyModifier<\/strong>, <strong>cutModifier<\/strong>, and <strong>pasteModifier<\/strong>. These functions help modify the data format before the corresponding operations are performed.<\/p>\n<p>Formatter functions are suitable for the following scenarios:<\/p>\n<p><strong>1. Format control.<\/strong><br \/>\nWhen the default clipboard behavior does not cover project needs, formatters can be used to apply the desired format. For instance, when a grid column configuration has <strong>editorType: &#8220;combobox&#8221;<\/strong>, which typically involves the &#8220;id&#8221; and &#8220;value&#8221; parameters for cells, the copy operation will be applied to &#8220;id&#8221;, which makes little sense. A more reasonable approach is to copy the visible label (&#8220;value&#8221;) shown in the combobox. The <strong>copyModifier<\/strong> function allows you to specify what gets copied to the clipboard:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">copyModifier<span class=\"sy0\">:<\/span> <span class=\"br0\">&#40;<\/span>value<span class=\"sy0\">,<\/span> cell<span class=\"sy0\">,<\/span> cut<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">editorType<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;combobox&quot;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> options <span class=\"sy0\">=<\/span> cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">options<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> option <span class=\"sy0\">=<\/span> options.<span class=\"me1\">find<\/span><span class=\"br0\">&#40;<\/span>opt <span class=\"sy0\">=&gt;<\/span> opt.<span class=\"me1\">id<\/span> <span class=\"sy0\">===<\/span> value<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> option <span class=\"sy0\">?<\/span> option.<span class=\"me1\">value<\/span> <span class=\"sy0\">:<\/span> value<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> value<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p><strong>2. Compatibility with external systems.<\/strong><br \/>\nFormatters come into play for data exchange with external tools by ensuring data compatibility. For instance,  it may be necessary to preserve a number mask when copying data from one grid table to another one. Here&#8217;s how the <strong>copyModifier<\/strong> function can preserve the applied number mask (dollar sign) when copying numeric cell content, instead of copying only the raw number:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> copyModifier<span class=\"br0\">&#40;<\/span>value<span class=\"sy0\">,<\/span> cell<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ Format numbers with currency prefix and two decimal places<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">type<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;number&quot;<\/span> <span class=\"sy0\">&amp;&amp;<\/span> cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">numberMask<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> numValue <span class=\"sy0\">=<\/span> parseFloat<span class=\"br0\">&#40;<\/span>value<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> `$$<span class=\"br0\">&#123;<\/span>numValue.<span class=\"me1\">toFixed<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#125;<\/span>`<span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ e.g., 10 becomes $10.00<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ other settings<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image8-1.gif\" alt=\"copy and paste data with preserved mask\" width=\"964\" height=\"824\" class=\"aligncenter size-full wp-image-14099\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/q1wj772g?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p><strong>3. Customization.<\/strong><br \/>\nIn some cases, required pieces of tabular data may come with additional symbols that you don&#8217;t want to see after pasting data (brackets, dashes, etc.). Therefore, it is great to have an opportunity to add extra info or remove excessive items from the data. In DHTMLX Grid, this kind of customization can be performed with the formatters:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">pasteModifier<span class=\"sy0\">:<\/span> <span class=\"br0\">&#40;<\/span>value<span class=\"sy0\">,<\/span> cell<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ Handle pasted numeric values<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">type<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;number&quot;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> cleaned <span class=\"sy0\">=<\/span> value.<span class=\"me1\">replace<\/span><span class=\"br0\">&#40;<\/span><span class=\"co2\">\/[^0-9.]\/g<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ Remove non-numeric characters<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> isNaN<span class=\"br0\">&#40;<\/span>cleaned<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">?<\/span> value <span class=\"sy0\">:<\/span> parseFloat<span class=\"br0\">&#40;<\/span>cleaned<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ Convert to number or keep original<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/ezgif.com-speed-3.gif\" alt=\"formatter function - customization\" width=\"980\" height=\"324\" class=\"aligncenter size-full wp-image-14114\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/dfj49xah?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p><strong>4. Preprocessing before validation.<\/strong><br \/>\nIf users paste dates in the &#8220;dd\/mm\/yyyy&#8221; format while your grid expects &#8220;yyyy-mm-dd&#8221;, the <strong>pasteModifier<\/strong> can help by converting the format during pasting and ensure it is valid:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">pasteModifier<span class=\"sy0\">:<\/span> <span class=\"br0\">&#40;<\/span>value<span class=\"sy0\">,<\/span> cell<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">type<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;date&quot;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> dateFormat <span class=\"sy0\">=<\/span> cell.<span class=\"me1\">column<\/span>.<span class=\"me1\">dateFormat<\/span> <span class=\"sy0\">||<\/span> <span class=\"st0\">&quot;dd\/mm\/yyyy&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> regex <span class=\"sy0\">=<\/span> <span class=\"co2\">\/^(\\d{2})\\\/(\\d{2})\\\/(\\d{4})$\/<\/span><span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ for dd\/mm\/yyyy<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> match <span class=\"sy0\">=<\/span> value.<span class=\"me1\">match<\/span><span class=\"br0\">&#40;<\/span>regex<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>match<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> date <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> <span class=\"kw4\">Date<\/span><span class=\"br0\">&#40;<\/span>`$<span class=\"br0\">&#123;<\/span>match<span class=\"br0\">&#91;<\/span><span class=\"nu0\">3<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">-<\/span>$<span class=\"br0\">&#123;<\/span>match<span class=\"br0\">&#91;<\/span><span class=\"nu0\">2<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">-<\/span>$<span class=\"br0\">&#123;<\/span>match<span class=\"br0\">&#91;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#125;<\/span>`<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>isNaN<span class=\"br0\">&#40;<\/span>date.<span class=\"me1\">getTime<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> `$<span class=\"br0\">&#123;<\/span>match<span class=\"br0\">&#91;<\/span><span class=\"nu0\">3<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">-<\/span>$<span class=\"br0\">&#123;<\/span>match<span class=\"br0\">&#91;<\/span><span class=\"nu0\">2<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">-<\/span>$<span class=\"br0\">&#123;<\/span>match<span class=\"br0\">&#91;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#125;<\/span>`<span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ ISO format<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> value<span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ validation will handle invalid cases<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> value<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image2.gif\" alt=\"formatter - preprocessing before validation\" width=\"920\" height=\"324\" class=\"aligncenter size-full wp-image-14101\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/dfj49xah?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>This ensures that pasted values are in the correct format before the grid validates or inserts them.<\/p>\n<p>It is also necessary to mention the main aspects of pasting data from the clipboard. The content is inserted in the selected range (defined by rangeSelection) in accordance with the order of  copying and adapts based on the range size: <\/p>\n<ul>\n<li>If the range is smaller than the copied area, the data is fully pasted when grid space allows.<\/li>\n<li>If the range is larger, copied values repeat cyclically to fill the full range.<\/li>\n<\/ul>\n<p>As a result, end-users will enjoy flexible and predictable pasting of project data in a spreadsheet-like manner.<\/p>\n<h5>Improved Drag-and-Drop Functionality<\/h5>\n<p>Drag-and-drop is a core feature for conveniently managing the structure of a grid table via the UI. In version 9.2, we focused on making the drag-and-drop capabilities of our Grid more intuitive and visually apparent. <\/p>\n<p>From now on, end-users can benefit from a visual indicator (a horizontal placeholder line) that appears dynamically as you drag any row or column across the table. The updated <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/configuration\/#drag-n-drop\" rel=\"noopener\" target=\"_blank\">drag-and-drop functionality<\/a> will make it much easier to reorder tabular elements (rows and columns) or create hierarchical structures.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image11.gif\" alt=\"Improved drag-and-drop\" width=\"1796\" height=\"824\" class=\"aligncenter size-full wp-image-14103\" \/><\/p>\n<p>Apart from that, v9.2 also introduces the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage_dragpanel\/\" rel=\"noopener\" target=\"_blank\">DragPanel<\/a> module to make row dragging more intuitive. Besides its practical value, this tool helps deal with situations when conflicting configurations (such as BlockSelection or Clipboard modules) are used.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/07\/image9.gif\" alt=\"DragPanel functionality\" width=\"1764\" height=\"820\" class=\"aligncenter size-full wp-image-14104\" \/><a href=\"https:\/\/snippet.dhtmlx.com\/uevdwjuo?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>Under the hood, the DragPanel module is initialized with the <strong><a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/api\/grid_dragpanel_config\/\" rel=\"noopener\" target=\"_blank\">dragPanel<\/a><\/strong> property, which can be set as a boolean or an object (for extra config options). When the Grid configuration includes drag-and-drop for rows (<strong>dragItem: &#8220;row&#8221;<\/strong> or <strong>dragItem: &#8220;both&#8221;<\/strong>) or one of the two new modules (BlockSelection or Clipboard), the DragPanel module springs into action without extra code needed.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> grid <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">Grid<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;grid_container&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; columns<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;a&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;b&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; data<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;1&quot;<\/span><span class=\"sy0\">,<\/span> a<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A1&quot;<\/span><span class=\"sy0\">,<\/span> b<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B1&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;2&quot;<\/span><span class=\"sy0\">,<\/span> a<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A2&quot;<\/span><span class=\"sy0\">,<\/span> b<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;B2&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; dragItem<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;both&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"co1\">\/\/ enables row Drag-and-Drop<\/span><br \/>\n&nbsp; &nbsp; blockSelection<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span> <span class=\"co1\">\/\/ triggers `DragPanel` activation when `dragItem` is enabled<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ or<\/span><br \/>\n&nbsp; &nbsp; dragPanel<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span> <span class=\"co1\">\/\/ enables the `DragPanel` module<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>You can also customize how the DragPanel looks and behaves using <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/configuration\/#adjusting-dragpanel-module\" rel=\"noopener\" target=\"_blank\">various configuration settings<\/a>.<\/p>\n<p>These new visual cues greatly improve usability when managing grid structures, especially with hierarchical relations.<\/p>\n<h5>Other Improvements<\/h5>\n<h6>Updated Grid Export to Excel<\/h6>\n<p>Starting from version 9.2, exporting grid data to Excel becomes more functional and convenient. For this purpose, we adopted the <a href=\"https:\/\/github.com\/DHTMLX\/json2excel\" rel=\"noopener\" target=\"_blank\">JSON2Excel<\/a> library that simplifies the conversion of JSON files to Excel. With this novelty, you can expect seamless export of spans, number masks, dates, column&#8217;s editor options, and footers. You can test the updated export to Excel using this <a href=\"https:\/\/snippet.dhtmlx.com\/58oqij47?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">sample<\/a>. In this <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/usage\/#exporting-data-to-excel\" rel=\"noopener\" target=\"_blank\">section<\/a>, you can find instructions for exporting grid data to Excel. Also, check out the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/migration\/#91---92\" rel=\"noopener\" target=\"_blank\">migration notes<\/a> related to the export update.<\/p>\n<h6>Updated Integration Demos with Frameworks<\/h6>\n<p>DHTMLX Suite widgets are widely used in web apps based on popular JavaScript frameworks. To facilitate the implementation of our widgets in projects built with <a href=\"https:\/\/github.com\/DHTMLX\/angular-suite-demo\" rel=\"noopener\" target=\"_blank\">Angular<\/a>, <a href=\"https:\/\/github.com\/DHTMLX\/react-suite-demo\" rel=\"noopener\" target=\"_blank\">React<\/a>, <a href=\"https:\/\/github.com\/DHTMLX\/vue-suite-demo\" rel=\"noopener\" target=\"_blank\">Vue<\/a>, or <a href=\"https:\/\/github.com\/DHTMLX\/svelte-suite-demo\" rel=\"noopener\" target=\"_blank\">Svelte<\/a>, we refreshed the integration demos and added detailed <a href=\"https:\/\/docs.dhtmlx.com\/suite\/category\/backend-and-frameworks-integration\/\" rel=\"noopener\" target=\"_blank\">guides<\/a> in the documentation.<\/p>\n<p>That&#8217;s it about the novelties delivered in DHTMLX Suite 9.2. This release proves that even a minor update can deliver major improvements. If you want to go through the list of new Grid features and dig deeper into some specifics and details, check the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/whatsnew\/#version-92\" rel=\"noopener\" target=\"_blank\">&#8220;What&#8217;s New&#8221;<\/a> section. <\/p>\n<p><strong>Please, bear in mind that all new modules in v9.2 are available only in PRO edition of the DHTMLX Grid (or DHTMLX Suite) package!<\/strong> <\/p>\n<p>For those who are ready to test how the new modules turn DHTMLX Grid into a more intuitive and efficient tool for modern web apps, download a <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxSuite\/download.shtml\" rel=\"noopener\" target=\"_blank\">free 30-day trial version<\/a> of v9.2. Our current clients can access DHTMLX Suite 9.2 via their <a href=\"https:\/\/dhtmlx.com\/clients\/\" rel=\"noopener\" target=\"_blank\">Client&#8217;s Area<\/a>. <\/p>\n<h5>Related Materials<\/h5>\n<ul>\n<li><a href=\"https:\/\/docs.dhtmlx.com\/suite\/whatsnew\/#version-92\" rel=\"noopener\" target=\"_blank\">What&#8217;s new in v9.2<\/a><\/li>\n<li><a href=\"https:\/\/docs.dhtmlx.com\/suite\/\" rel=\"noopener\" target=\"_blank\">DHTMLX Suite documentation<\/a><\/li>\n<li><a href=\"https:\/\/snippet.dhtmlx.com\/i9rm4vsd?tag=grid&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">DHTMLX Suite code snippets<\/a><\/li>\n<li><a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxSuite\/download.shtml\" rel=\"noopener\" target=\"_blank\">Free 30-day trial version<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>We are thrilled to present a new update to our JavaScript UI widgets library, bringing the Suite&#8217;s Grid widget to a new level. While nominally it is a minor &#8230;<\/p>\n","protected":false},"author":101014,"featured_media":14090,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[70],"tags":[33,10],"class_list":["post-14088","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-releases","tag-all-posts","tag-dhtmlxsuite"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14088","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/101014"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=14088"}],"version-history":[{"count":20,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14088\/revisions"}],"predecessor-version":[{"id":14378,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14088\/revisions\/14378"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/14090"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=14088"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=14088"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=14088"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}