Repository: jupyter-widgets/ipydatagrid (language: python)

Issue:
Trying to grid an empty dataframe throws JavaScript error in 1.3.0
**Describe the bug**

I like to create an empty table (just the columns) before the user hits a button to populate the data in the table. This worked fine in 1.2.1 however appears to be broken in 1.3.0:

![image](https://github.com/bloomberg/ipydatagrid/assets/80677094/0584a1b1-ec99-4f38-9b95-4fc34d267f47)

```
Model class 'DataGridModel' from module 'ipydatagrid' is loaded but can not be instantiated
Error: Failed to deserialize data
    at https://__REDACTED__/user/mktrarcm46c358d0/lab/extensions/bqplot/static/568.d098e2e89d2e163b9080.js?v=d098e2e89d2e163b9080:1:408310
    at Object.e [as deserialize] (https://__REDACTED__/user/mktrarcm46c358d0/lab/extensions/bqplot/static/568.d098e2e89d2e163b9080.js?v=d098e2e89d2e163b9080:1:408608)
    at Object.deserialize (https://__REDACTED__/user/mktrarcm46c358d0/lab/extensions/ipydatagrid/static/787.f307b1ca46997f4a9051.js?v=f307b1ca46997f4a9051:1:59363)
    at y._deserialize_state (https://__REDACTED__/user/mktrarcm46c358d0/lab/extensions/tf-jupyter-widgets/static/vendors-node_modules_jupyter-widgets_base_lib_index_js.3eb466ed8ca6ec866025.js:1675:54)
    at f._make_model (https://__REDACTED__/user/mktrarcm46c358d0/lab/extensions/@jupyter-widgets/jupyterlab-manager/static/150.1a6d6a3a0542a41bec5a.js?v=1a6d6a3a0542a41bec5a:1:7933)
```

**To Reproduce**

```
import ipydatagrid
import pandas as pd

columns = [
    "a", "b", "c",
]

df = pd.DataFrame(dict(zip(columns, len(columns) * [[]])))

ipydatagrid.DataGrid(
    dataframe=df,
)
```

**Expected behavior**

Empty grid is displayed like 1.2.1:

![image](https://github.com/bloomberg/ipydatagrid/assets/80677094/988c5a0c-aad9-42e0-af0d-c35134a631e6)


**Screenshots**

if I pass a dataframe with a single row, naturally it works, but I'd rather show a completely empty table

![image](https://github.com/bloomberg/ipydatagrid/assets/80677094/6602b611-4893-4e31-bae3-3560ee44963d)





Discussion / hints:

Fix patch:
diff --git a/js/datagrid.ts b/js/datagrid.ts
index ae06a4ce..05d4eeb8 100644
--- a/js/datagrid.ts
+++ b/js/datagrid.ts
@@ -84,13 +84,22 @@ function serialize_data(data: DataSource, manager: any): any {
 function deserialize_data(data: any, manager: any): DataSource {
   const deserialized_data: any = {};
   for (const column of Object.keys(data.data)) {
+    deserialized_data[column] = [];
+
+    if (Array.isArray(data.data[column])) {
+      deserialized_data[column] = data.data[column];
+      continue;
+    }
+
     if (data.data[column].type == 'raw') {
       deserialized_data[column] = unpack_raw_data(data.data[column].value);
     } else {
-      deserialized_data[column] = array_or_json_serializer.deserialize(
-        data.data[column],
-        manager,
-      );
+      if (data.data[column].value.length !== 0) {
+        deserialized_data[column] = array_or_json_serializer.deserialize(
+          data.data[column],
+          manager,
+        );
+      }
     }
   }
   return new DataSource(deserialized_data, data.fields, data.schema, true);


Test patch:
diff --git a/ui-tests-ipw8/tests/ipydatagrid.test.ts-snapshots/dark-empty-ipynb-cell-0-linux.png b/ui-tests-ipw8/tests/ipydatagrid.test.ts-snapshots/dark-empty-ipynb-cell-0-linux.png
new file mode 100644
index 00000000..a478abcd
Binary files /dev/null and b/ui-tests-ipw8/tests/ipydatagrid.test.ts-snapshots/dark-empty-ipynb-cell-0-linux.png differ
diff --git a/ui-tests-ipw8/tests/ipydatagrid.test.ts-snapshots/light-empty-ipynb-cell-0-linux.png b/ui-tests-ipw8/tests/ipydatagrid.test.ts-snapshots/light-empty-ipynb-cell-0-linux.png
new file mode 100644
index 00000000..7505438c
Binary files /dev/null and b/ui-tests-ipw8/tests/ipydatagrid.test.ts-snapshots/light-empty-ipynb-cell-0-linux.png differ
diff --git a/ui-tests-ipw8/tests/notebooks/empty.ipynb b/ui-tests-ipw8/tests/notebooks/empty.ipynb
new file mode 100644
index 00000000..4bf5028c
--- /dev/null
+++ b/ui-tests-ipw8/tests/notebooks/empty.ipynb
@@ -0,0 +1,42 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c8271791-1c8f-4b79-b105-f57576533aaa",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from ipydatagrid import DataGrid, TextRenderer, BarRenderer, Expr, ImageRenderer\n",
+    "\n",
+    "import pandas as pd\n",
+    "\n",
+    "columns = [\"a\", \"b\", \"c\"]\n",
+    "\n",
+    "df = pd.DataFrame(dict(zip(columns, len(columns) * [[]])))\n",
+    "DataGrid(df)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.12.3"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}