Reputation: 397
I'm writing a JavaScript function to allow users of an application built using Oracle Application Express 21.1 to paste data from Excel spreadsheets into an Interactive Grid and save the data. Using the APEX JavaScript API I can update the model of the Interactive Grid with the data; the pasted values display correctly and when I subsequently access the model the correct values are returned.
However when the Interactive Grid is saved, those values aren't saved to the underlying database table. What happens is:
The grid is a simple Interactive Grid region based on the default EMP table, with a static ID of EmployeeGrid, and saves using the Interactive Grid process that is automatically generated when the grid was created.
I have entered the following code in the Execute when Page Loads section:
$("#EmployeesGrid_ig").on('paste', onPaste);
I have entered the following code in the Function and Global Variable Declaration section:
function onPaste(e) {
if (!e.originalEvent.clipboardData ||
!e.originalEvent.clipboardData.items) return;
let items = e.originalEvent.clipboardData.items;
let data;
for (let i = 0; i < items.length; i++) {
if (items[i].type == 'text/plain') {
data = items[i];
break;
}
}
if (!data) return;
data.getAsString(function(text) {
// Split the clipboard data into rows.
text = text.replace(/\r/g, '').trim('\n');
let rowsOfText = text.split('\n');
let rows = [];
// Iterate over each row of text and push the trimmed data into rows[]
rowsOfText.forEach(function(rowOfText) {
let row = rowOfText.split('\t').map(function(colAsText) {
return colAsText.trim().replace(/^"(.*)"$/, '$1');
});
rows.push(row);
});
// We get the focused element (i.e. where the user wants to paste).
let $focused = $('.is-focused');
// We get metadata from the Interactive Grid.
let rowId = $focused.closest('tr').data('id');
let columnIndex = $focused.index();
let headerIndex = $focused.closest('table').find('th').eq(columnIndex).data('idx');
let ig$ = apex.region("EmployeesGrid").widget();
let grid = ig$.interactiveGrid("getCurrentView");
let model = grid.model;
let columns = grid.getColumns();
let record = model.getRecord(rowId);
//Map visible columns
let visibleColumns = columns.filter(function (val) { return !val.hidden; });
visibleColumns.sort(function(a,b){return a.index - b.index;});
// Complete the Promise after the grid is out of editing mode.
rows.forEach(function(row) {
row.forEach(function(value, offset) {
if (record !== null) {
visibleColumns.forEach(function(column, visColIdx) {
if (visColIdx === (headerIndex + offset)) {
if (model.allowEdit(record)) {
model.setValue(record, column.property, Number(value));
}
}
});
}
});
// To change record, get current record index and then get next record.
let recordIndex = model.indexOf(record);
record = model.recordAt(recordIndex + 1);
});
});
}
I have created a sample application on apex.oracle.com to demonstrate the behaviour, please note that I have set the grid to allow updates to existing rows only and that only the Sal and Comm number columns can be updated.
Upvotes: 1
Views: 2367
Reputation: 755
Another approach is to use apex.locale JSAPI, is more APEX native way and won't cause issues in the future with APEX upgrades
var number = apex.locale.toNumber( "1,234.56" );
number = apex.locale.toNumber( "$1,234.56", "FML999G999G990D00" );
number = apex.locale.toNumber( "$1234.56", "FML999G999G990D00" );
Check this out https://docs.oracle.com/en/database/oracle/application-express/21.2/aexjs/apex.locale.html#.toNumber
Upvotes: 0
Reputation: 397
I found a similar question raised on Oracle Communities where user Woodrow could visually see values that were automatically updated in an Interactive Grid column but those values weren't present when the page was submitted.
The answer they found was to set the value as a string:
model.setValue(record, column.property, value);
instead of a number:
model.setValue(record, column.property, Number(value));
This was necessary even if the column was declared as a 'Number' column in APEX.
Upvotes: 1