事件

ReportSheet具有可以在报表数据更改或提交时绑定的数据输入事件。

通过以下事件,用户可以在数据更改时验证所有数据更改或取消操作,还可以获取服务器的反馈结果,然后在UI中显示结果。

在新窗口中打开演示可以打开设计器: ReportSheet支持以下数据输入事件。您可以使用以下代码绑定数据输入事件: ReportSheetDataChanging和ReportSheetDataChanged ReportSheetDataChanging在报表表格通过更新、插入或删除进行更改时发生。允许验证或取消数据操作。 ReportSheetDataChanged在报表表格通过更新、插入或删除更改数据时发生。允许将数据更改提交到服务器。 ReportSheetRecordsSubmitting和ReportSheetRecordsSubmitted ReportSheetRecordsSubmitting在报表表格提交更改到服务器之前发生。允许对所有数据更改进行最终验证或取消操作。 ReportSheetRecordsSubmitted在报表表格将更改提交到服务器后发生。允许用户提供来自服务器的提交结果的UI反馈。
window.onload = async () => { const loadingTip = addLoadingTip(); const { spread, designer } = createSpreadAndDesigner(); const res = await fetch('$DEMOROOT$/zh/sample/features/report-sheet/data-entry/events/spread.json'); await spread.fromJSON(correctTableUrl(await res.json())); loadingTip.remove(); _bindDataEntrySubmitEvents(spread); if (designer) { designer.refresh(); } } function createSpreadAndDesigner() { const demoHost = document.getElementById('demo-host'); if (window !== top) { return { spread: new GC.Spread.Sheets.Workbook(demoHost, { sheetCount: 1 }), } } else { const designer = new GC.Spread.Sheets.Designer.Designer(demoHost, undefined, undefined, { sheetCount: 1 }); return { designer, spread: designer.getWorkbook(), } } } function addLoadingTip() { const div = document.createElement('div'); div.style.position = 'absolute'; div.style.inset = '0'; div.style.display = 'flex'; div.style.alignItems = 'center'; div.style.justifyContent = 'center'; div.style.background = 'white'; div.style.zIndex = '100'; div.textContent = 'Loading data from server ...'; document.body.appendChild(div); return div; } function correctTableUrl(json) { const baseUrl = '$DEMOROOT$'; const localUrl = 'http://localhost:8070/spreadjs/demos'; const replaceUrl = (obj) => { if (obj && obj.url && obj.url.startsWith(localUrl)) { obj.url = obj.url.replace(localUrl, baseUrl); } } if (json.dataManager && json.dataManager.tables) { json.dataManager.tables.forEach((table) => { if (table.dataSourceOption && table.dataSourceOption.remote) { Object.values(table.dataSourceOption.remote).forEach(replaceUrl); } }); } return json; } let time; function _showWindowTip (message, success) { let tipContainer = document.querySelector('.tip-container'); if (!tipContainer) { const div = document.createElement('div'); div.classList.add("tip-container"); document.body.appendChild(div); tipContainer = div; } let innerContainer = document.createElement('div'); innerContainer.className = `tip-inner-container ${success ? 'success' : 'failed'}`; innerContainer.innerHTML = ` <h1>${success ? "Success" : "Failed"}</h1> <p>${message}</p> `; tipContainer.appendChild(innerContainer); if (time) { clearTimeout(time); } time = setTimeout(() => { tipContainer.innerHTML = ""; clearTimeout(time); time = 0; }, 4000); } function _bindDataEntrySubmitEvents (spread) { let reportSheet = spread.getActiveSheetTab(); if (reportSheet) { reportSheet.bind(GC.Spread.Sheets.Events.ReportSheetDataChanging, (event, args) => { let { row, col, newValue, type } = args; if (type === "update") { if (col <= 4 && typeof newValue !== "string") { args.cancel = true; _showWindowTip("New value should be string at col " + col); } else if (col === 5 && typeof newValue !== "number") { args.cancel = true; _showWindowTip("New value should be number at col " + col); } else { type = type[0].toUpperCase() + type.substring(1); _showWindowTip(`${(type)} at cell Row: ${row} col: ${col}`, true); } } else { type = type[0].toUpperCase() + type.substring(1); _showWindowTip(`${type} at cell Row: ${row} col: ${col}`, true); } }); reportSheet.bind(GC.Spread.Sheets.Events.ReportSheetRecordsSubmitted, (event, args) => { let { updateSuccessRecords, updateFailedRecords, deleteSuccessRecords, deleteFailedRecords } = args; let updateSuccessCells = [], deleteSuccessCells = [], updateFailedCells = [], deleteFailedCells = []; updateSuccessRecords.forEach((r) => { for (let key in r.info) { if (r.info.hasOwnProperty(key) && r.info[key].state === "updated") { updateSuccessCells.push({ row: r.info[key].row, col: r.info[key].col, }); } } }); deleteSuccessRecords.forEach((r) => { for (let key in r.info) { if (r.info.hasOwnProperty(key)) { deleteSuccessCells.push({ row: r.info[key].row, col: r.info[key].col, }); } } }); updateFailedRecords.forEach((r) => { for (let key in r.info) { if (r.info.hasOwnProperty(key) && r.info[key].state === "updated") { updateFailedCells.push({ row: r.info[key].row, col: r.info[key].col, reason: r.reason === undefined ? "null" : r.reason }); } } }); deleteFailedRecords.forEach((r) => { for (let key in r.info) { if (r.info.hasOwnProperty(key)) { deleteFailedCells.push({ row: r.info[key].row, col: r.info[key].col, reason: r.reason === undefined ? "null" : r.reason }); } } }); updateSuccessCells.forEach((cell, i) => { setTimeout(() => { _showWindowTip(`Update successfully at cell Row: ${cell.row} col: ${cell.col}`, true); }, i * 100); }); setTimeout(() => { deleteSuccessCells.forEach((cell, i) => { setTimeout(() => { _showWindowTip(`Delete successfully at cell Row: ${cell.row} col: ${cell.col}`, true); }, i * 100); }); }, updateSuccessCells.length * 100); setTimeout(() => { updateFailedCells.forEach((cell, i) => { setTimeout(() => { _showWindowTip(`Update failed at cell Row: ${cell.row} col: ${cell.col}, reason is ${cell.reason}`); }, i * 100); }); }, (updateSuccessCells.length + deleteSuccessCells.length) * 100); setTimeout(() => { deleteFailedCells.forEach((cell, i) => { setTimeout(() => { _showWindowTip(`Delete failed at cell Row: ${cell.row} col: ${cell.col}, reason is ${cell.reason}`); }, i * 100); }); }, (updateSuccessCells.length + deleteSuccessCells.length + updateFailedCells.length) * 100); }); } }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="spreadjs culture" content="zh-cn" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css"> <link rel="stylesheet" type="text/css" href="styles.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-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.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> const designerDependencyScripts = [ '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-io/dist/gc.spread.sheets.io.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer-resources-cn/dist/gc.spread.sheets.designer.resource.cn.min.js', '$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js', '$DEMOROOT$/spread/source/js/designer/license.js', ] function appendScriptNode (src) { const script = document.createElement('script'); script.src = src; script.async = false; script.type = 'text/javascript'; document.head.appendChild(script); } if (top === window) { // not in iframe designerDependencyScripts.forEach(appendScriptNode); } </script> <script src="app.js" type="text/javascript"></script> </head> <body> <div class="sample-tutorial"> <div id="demo-host"></div> </div> </body> </html>
body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } #demo-host { width: 100%; height: 100%; overflow: hidden; float: left; } .tip-container { position: absolute; display: flex; align-items: center; justify-content: start; z-index: 100; min-width: 300px; min-height: 60%; max-height: 100%; right: 0; top: 0; overflow: hidden; flex-direction: column; } .tip-inner-container { position: relative; display: flex; height: 52px; background-color: white; flex-direction: column; min-width: 200px; margin-bottom: 10px; padding: 0px 25px 0 10px; border-radius: 10px; box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 5px 0px, rgba(0, 0, 0, 0.1) 0px 2px 3px 0px; align-items: start; animation-name: tip-animation; animation-duration: 4s; animation-fill-mode: forwards; color: rgb(51, 51, 51); font-family: sans-serif; } .success { border-left: solid 8px rgb(154, 233, 140); } .failed { border-left: solid 8px rgb(227, 144, 143); } .tip-inner-container h1 { margin: 0; padding-top: 5px; font-size: 17.6px; font-weight: 500; } .tip-inner-container p { margin: 0; padding-top: 5px; font-size: 12.8px; } @keyframes tip-animation { 0% { left: 300px; opacity: 0; } 20% { left: 10px; opacity: 1; } 75% { left: 10px; opacity: 1; } 100% { left: 300px; opacity: 0; } }