Repository: highcharts/highcharts (2025-07-24T08:06:01Z)

Issue:
Resized Column Widths Missing in getOptions() When No Initial Width is Defined
### Expected behaviour
When a user resizes a column in the Grid component, the updated column width should be reflected in the output of Board.getOptions(), regardless of whether an initial width was specified in the configuration.

### Actual behaviour
If an initial width is defined for a column via gridOptions.columns, any subsequent manual resizing is correctly reflected in Board.getOptions().

However, if no initial width is defined for a column (e.g. when relying on default widths), any user-driven changes to that column’s width are not persisted in the result of Board.getOptions().

Notably, defining columnDefaults.width does not resolve this issue.

### Live demo with steps to reproduce
[JSFiddle demo](https://jsfiddle.net/trip57/qo2pkt70/27/)

**Steps to reproduce:**

1. Load the dashboard without the columns option set in the Grid configuration.
2. Manually resize any column via the user interface.
3. Click the “Print out JSON” button.
4. Inspect the console output.
    - Actual: components[0].gridOptions does not include the updated column width.
5. Uncomment the columns option in the JavaScript code and click Run to reload the dashboard.
6. Repeat steps 2–3.
    - **Expected:** The updated column width appears in gridOptions.

### Product version
<!-- Highcharts Core, Stock, Maps, Gantt, or Dashboards, plus version number -->
Highcharts Dashboards v3.5.0 (2025-07-14)

### Affected browser(s)
Chrome version 138.0.7204.101 64-bit


<!-- ASANA TASK ID (do not delete): 1210811450840657 -->


Discussion:
Hi! Thanks for reporting this.

The problem consists of two layers, one of which appears to be a bug and the other is intentional.

**Intentional layer:** when neither the width of any column nor `resizing.mode` is specified, the default distribution strategy is `full`, which doesn’t support `column.width` option but relies on CSS. This behavior is intentional because of the need to maintain backward compatibility and will be changed in the next major release - at that point, resizing modes will have more meaningful names and all of them will support the `column.width` option.

**Unintentional layer:** `getOptions()` doesn’t take into account additional fields in the `grid.userOptions` object. This is a bug. As a workaround, you can retrieve the grid’s options via `component.grid.userOptions`.

https://jsfiddle.net/BlackLabel/m8b4cv76/



Patch:
diff --git a/samples/dashboards/cypress/component-grid-resize/demo.css b/samples/dashboards/cypress/component-grid-resize/demo.css
new file mode 100644
index 00000000000..d9b6937c9e0
--- /dev/null
+++ b/samples/dashboards/cypress/component-grid-resize/demo.css
@@ -0,0 +1,6 @@
+@import url("https://code.highcharts.com/dashboards/css/dashboards.css");
+@import url("https://code.highcharts.com/dashboards/css/datagrid.css");
+
+#dashboard-col-1 {
+    height: 400px;
+}
diff --git a/samples/dashboards/cypress/component-grid-resize/demo.html b/samples/dashboards/cypress/component-grid-resize/demo.html
new file mode 100644
index 00000000000..75cd11451ab
--- /dev/null
+++ b/samples/dashboards/cypress/component-grid-resize/demo.html
@@ -0,0 +1,1 @@
+<div id="container"></div>
diff --git a/samples/dashboards/cypress/component-grid-resize/demo.mjs b/samples/dashboards/cypress/component-grid-resize/demo.mjs
new file mode 100644
index 00000000000..0f0dc32c4cc
--- /dev/null
+++ b/samples/dashboards/cypress/component-grid-resize/demo.mjs
@@ -0,0 +1,39 @@
+import Dashboards from '../../../../code/dashboards/es-modules/masters/dashboards.src.js';
+import '../../../../code/dashboards/es-modules/masters/modules/layout.src.js';
+import Grid from '../../../../code/datagrid/es-modules/masters/datagrid.src.js';
+
+Dashboards.GridPlugin.custom.connectGrid(Grid);
+Dashboards.PluginHandler.addPlugin(Dashboards.GridPlugin);
+
+Dashboards.board('container', {
+    dataPool: {
+        connectors: [{
+            id: 'data',
+            type: 'JSON',
+            options: {
+                data: [
+                    ['Product Name', 'Quantity'],
+                    ['Laptop', 100],
+                    ['Smartphone', 150],
+                    ['Desk Chair', 120]
+                ]
+            }
+        }]
+    },
+    gui: {
+        layouts: [{
+            rows: [{
+                cells: [{
+                    id: 'cell-1'
+                }]
+            }]
+        }]
+    },
+    components: [{
+        renderTo: 'cell-1',
+        type: 'Grid',
+        connector: {
+            id: 'data'
+        }
+    }]
+});
diff --git a/ts/Dashboards/Components/DataGridComponent/DataGridComponent.ts b/ts/Dashboards/Components/DataGridComponent/DataGridComponent.ts
index 4815e2c812c..5af0ea4b717 100644
--- a/ts/Dashboards/Components/DataGridComponent/DataGridComponent.ts
+++ b/ts/Dashboards/Components/DataGridComponent/DataGridComponent.ts
@@ -289,9 +289,10 @@ class DataGridComponent extends Component {
      * @internal
      */
     public override getOptions(): Partial<Options> {
+        const optionsCopy = merge(this.options);
+        optionsCopy.gridOptions = this.grid?.getOptions();
 
         // Remove the table from the options copy if the connector is set.
-        const optionsCopy = merge(this.options);
         if (optionsCopy.connector?.id) {
             delete optionsCopy.gridOptions?.dataTable;
         } else if (optionsCopy.gridOptions?.dataTable?.id) {
diff --git a/ts/Grid/Core/Grid.ts b/ts/Grid/Core/Grid.ts
index 53ce21e2ff5..8464d393235 100644
--- a/ts/Grid/Core/Grid.ts
+++ b/ts/Grid/Core/Grid.ts
@@ -1082,7 +1082,7 @@ class Grid {
      * @returns
      * Grid options.
      */
-    public getOptions(onlyUserOptions = true): Globals.DeepPartial<Options> {
+    public getOptions(onlyUserOptions = true): Partial<Options> {
         const options =
             onlyUserOptions ? merge(this.userOptions) : merge(this.options);
 


Test patch:
diff --git a/test/cypress/grid/integration/resize.cy.js b/test/cypress/grid/integration/resize.cy.js
new file mode 100644
index 00000000000..2b7320bbf18
--- /dev/null
+++ b/test/cypress/grid/integration/resize.cy.js
@@ -0,0 +1,27 @@
+describe('Grid resize.', () => {
+    beforeEach(() => {
+        cy.visit('dashboards/cypress/component-grid-resize');
+    });
+
+    it('Changes in the grid should be reflected in the options', () => {
+        cy.get('.highcharts-datagrid-header-cell').eq(0).as('cell');
+        cy.get('@cell').find('.highcharts-datagrid-column-resizer').as('resizer');
+        cy.get('@resizer').trigger('mousedown');
+        cy.get('@resizer').trigger('mousemove', { pageX: 100 });
+        cy.get('@resizer').trigger('mouseup');
+
+        cy.get('@cell').invoke('width').should('be.lessThan', 400);
+
+        cy.board().then((board) => {
+            const componentOptions = board.getOptions().components[0];
+            const gridOptions = componentOptions.gridOptions;
+
+            assert.equal(componentOptions.type, 'Grid', 'Component type should be Grid');
+            assert.notOk(gridOptions.columnDefaults, 'Column defaults should not be defined');
+            assert.ok(gridOptions.columns, 'Columns should be defined');
+            assert.notOk(gridOptions.credits, 'Credits should not be defined');
+            assert.notOk(gridOptions.lang, 'Language should not be defined');
+            assert.notOk(gridOptions.rendering, 'Rendering should not be defined');
+        });
+    });
+});