单元格级别绑定

SpreadJS 支持单元格级别的数据绑定,允许将数据对象的属性直接绑定到指定的单元格。通过这种方式,数据源与单元格之间可以保持自动同步,修改单元格内容会自动更新数据源,修改数据源也会反映到单元格中。这种绑定方式特别适用于表单类应用,如个人信息录入、数据编辑等场景。

概述 本 Demo 展示了如何使用 SpreadJS 的单元格级别数据绑定功能,将 JavaScript 对象的属性绑定到工作表的指定单元格。Demo 演示了数据绑定、事件监听和双向数据同步的完整流程,包括嵌套对象属性的绑定(如 address.postcode)。 实现思路 创建数据对象(包含嵌套属性的 person 对象) 使用 CellBindingSource 包装数据对象,创建数据源 通过 setBindingPath 方法为单元格设置绑定路径 调用 setDataSource 方法将数据源设置到工作表 监听 SelectionChanged 事件,显示选中单元格的绑定路径 监听 CellChanged 事件,同步单元格变化到 HTML 输入框 实现数据更新函数,允许通过 HTML 输入框修改数据源并刷新表格 代码解析 创建数据源并设置绑定路径 这段代码创建了数据源并将其绑定到单元格。CellBindingSource 构造函数接收数据对象,setBindingPath 的第三个参数支持嵌套属性路径(如 "address.postcode"),setDataSource 方法将包装后的数据源应用到工作表。 监听选择变化事件 当用户选择不同的单元格时,SelectionChanged 事件被触发,通过 getBindingPath 方法获取当前单元格的绑定路径并显示在页面上。 监听单元格内容变化事件 当单元格内容被修改时,CellChanged 事件触发,由于单元格已绑定到 person 对象,对象的属性值会自动更新。这段代码将更新后的数据同步显示到页面的输入框中,实现了从表格到界面的数据同步。 更新数据源并刷新表格 这些函数允许通过 HTML 输入框修改数据源对象的属性。修改后调用 sheet.repaint() 方法刷新表格显示,实现了从界面到表格的数据同步。 运行效果 表格中的灰色单元格已绑定到 person 对象的相应属性 点击绑定单元格时,页面底部会显示该单元格的绑定路径(如 "name"、"address.postcode") 直接在表格中修改单元格内容,右侧的输入框会自动更新为最新的数据值 在右侧输入框中修改数据并按键盘,表格中对应的单元格会实时更新 支持嵌套属性绑定,如 address.postcode 绑定到第 5 行第 2 列 API 参考 CellBindingSource 构造函数 data:要绑定的数据对象 setBindingPath 方法 row:单元格行索引 col:单元格列索引 path:绑定路径,支持嵌套属性(如 "address.postcode") getBindingPath 方法 返回指定单元格的绑定路径字符串 setDataSource 方法 data:数据源(对于单元格级别绑定,应为 CellBindingSource 对象) reset:可选,是否重置工作表
var person, sheet; window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss")); initSpread(spread); }; function initSpread(spread) { var spreadNS = GC.Spread.Sheets; sheet = spread.sheets[0]; sheet.suspendPaint(); sheet.setColumnWidth(0, 120); sheet.setColumnWidth(1, 120); sheet.setColumnWidth(2, 120); sheet.setValue(0, 0, 'cell-binding'); sheet.setValue(2, 1, 'Name'); sheet.setValue(3, 1, 'Age'); sheet.setValue(4, 1, 'Sex'); sheet.setValue(5, 1, 'Address.postcode'); person = { name: "Wang Feng", age: 25, sex: "Male", address: { postcode: "710075" } }; document.getElementById("personName").value=person.name || ""; document.getElementById("personAge").value=person.age || ""; document.getElementById("personSex").value=person.sex || ""; document.getElementById("personPostcode").value=person.address.postcode || ""; var source = new spreadNS.Bindings.CellBindingSource(person); sheet.setBindingPath(2, 2, "name"); sheet.setBindingPath(3, 2, "age"); sheet.setBindingPath(4, 2, "sex"); sheet.setBindingPath(5, 2, "address.postcode"); sheet.setDataSource(source); sheet.setSelection(2, 2, 1, 1); var path = sheet.getBindingPath(2, 2); sheet.getRange(2, 2, 4, 1).backColor("rgb(208,206,206)"); document.getElementById("bindingPath").innerHTML=path || ""; sheet.bind(spreadNS.Events.SelectionChanged, function() { var activeCell = sheet.getSelections()[0]; var path = sheet.getBindingPath(activeCell.row, activeCell.col); document.getElementById("bindingPath").innerHTML=path || ""; }); sheet.bind(spreadNS.Events.CellChanged, function() { document.getElementById("personName").value=person.name || ""; document.getElementById("personAge").value=person.age || ""; document.getElementById("personSex").value=person.sex || ""; document.getElementById("personPostcode").value=person.address.postcode || ""; }); sheet.resumePaint(); }; var updateName = function(value) { if (person && sheet) { person.name = value; sheet.repaint(); } }; var updateAge = function(value) { if (person && sheet) { person.age = value; sheet.repaint(); } }; var updateSex = function(value) { if (person && sheet) { person.sex = value; sheet.repaint(); } }; var updatePostcode = function(value) { if (person && sheet) { person.address.postcode = value; sheet.repaint(); } };
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta name="spreadjs culture" content="zh-cn" /> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> <div class="options-container"> <div class="option-row"> <label style="background-color:#F4F8EB;">Select one of the gray cells to get its binding. You can also change the Person object below to see it change in the Spread instance: change any of the text in the text boxes below.</label> </div> <div class="option-row"> <label>Name:&nbsp;&nbsp;</label> <input type="text" id="personName" onkeyup="updateName(this.value)" /> <label>Age:&nbsp;&nbsp;</label> <input type="text" id="personAge" onkeyup="updateAge(this.value)" /> <label>Sex:&nbsp;&nbsp;</label> <input type="text" id="personSex" onkeyup="updateSex(this.value)" /> <label>Postcode:&nbsp;&nbsp;</label> <input type="text" id="personPostcode" onkeyup="updatePostcode(this.value)" /> <label>GetBindingPath:&nbsp;&nbsp;</label> <label id="bindingPath" style="color:darkgreen"></label> </div> </div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } label { display: block; margin-bottom: 6px; } input { padding: 4px 6px; } input[type=button] { margin-top: 6px; display: block; } input[type=text] { margin-top: 6px; margin-bottom: 6px; display: block; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }