This example extends the Batch Editing demo by adding support for rich styles and rich objects such as media files, images, and hyperlinks.
Users can add, update, and delete multiple records and styles directly within the grid, with full undo and redo capabilities for unlimited steps.
Once the edits are finalized, all changes are committed to the server in a single transaction, ensuring data consistency and efficiency.
The server responds with the updated rows, including assigned primary key values
(e.g., Product ID) for any newly inserted records.
CREATE TABLE Product (
ProductID INT PRIMARY KEY, -- Primary key
ProductName NVARCHAR(255) NOT NULL, -- Product name
Image VARCHAR(MAX) NULL, -- Base64-encoded image
QuantityPerUnit NVARCHAR(255) NULL, -- Packaging details
UnitPrice DECIMAL(18, 2) NULL, -- Price per unit
UnitsInStock SMALLINT NULL, -- Current stock
UnitsOnOrder SMALLINT NULL, -- Pending orders
ReorderLevel SMALLINT NULL, -- Restock threshold
Discontinued BIT NOT NULL, -- Active/Inactive flag
-- Fields to support rich editing in PQGrid
pq_cellattr NVARCHAR(MAX) NULL,
pq_cellprop NVARCHAR(MAX) NULL,
pq_cellstyle NVARCHAR(MAX) NULL
);
Field definitions and data types may vary depending on the SQL database in use.
In this example, product images are stored in the Image column
as Base64 strings for simplicity.
Alternatively, images can be stored in a binary format, but they must be converted
to Base64 when rendering inside the grid.
The grid posts a consolidated list to the server (via the saveChanges
function in this example), regardless of the server-side environment.
This list is obtained by calling the API:
grid.getChanges({ format: 'byVal' })
The returned list object contains three sublists:
addList, deleteList,
and updateList.
list: {
addList: [
{
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
},
{
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
}
// ...
],
deleteList: [
{ id: 10 },
{ id: 29 }
// ...
],
updateList: [
{
id: 3,
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
},
{
id: 7,
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
}
// ...
]
}
Here, id refers to the primary key of the records, which is
ProductID in this example.
Tip: Open your browser’s developer network console to inspect the sample request and response payloads in real time.
The server processes the received list and returns a response
in the same structure.
The main difference between the request and the response lies in the
addList:
the server assigns primary key values (id) to the newly inserted rows.
Repetition of records in the other lists acts as confirmation for the
grid.commit() method, indicating that the server successfully
processed those records.
list: {
addList: [
{
id: 1000,
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
},
{
id: 1001,
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
}
// ...
],
deleteList: [
{ id: 10 },
{ id: 29 }
// ...
],
updateList: [
{
id: 3,
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
},
{
id: 7,
field1: value1,
field2: value2,
pq_cellattr: {...},
pq_cellprop: {...},
pq_cellstyle: {...}
}
// ...
]
}