Events

ReportSheet have data entry events that can be bound while report data changing or submitting.

With below events, users can valid all data changes or cancel the operation while data changing, can also get the feedback result of server then show the result in UI.

Open the demo in new window can open the designer ReportSheet supports below data entry events. You can use the following code to bind the data entry events: ReportSheetDataChanging and ReportSheetDataChanged ReportSheetDataChanging occurs when the report sheet is changing by update, insert or delete. Allows validating or cancellation of the data operation. ReportSheetDataChanged occurs when the report sheet data has changed by update, insert or delete. Allows submitting data changes to the server. ReportSheetRecordsSubmitting and ReportSheetRecordsSubmitted ReportSheetRecordsSubmitting occurs before the report sheet submitting changes to server. Allows final validation of all data changes or cancellign the operation. ReportSheetRecordsSubmitted occurs after the report sheet submitted the changes to server. Allow user to provide UI feedback of the submit results from the server.
window.onload = async () => { const loadingTip = addLoadingTip(); const { spread, designer } = createSpreadAndDesigner(); const res = await fetch('$DEMOROOT$/en/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" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css"> <link rel="stylesheet" type="text/css" href="styles.css"> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script> const designerDependencyScripts = [ '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer-resources-en/dist/gc.spread.sheets.designer.resource.en.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/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; } }