Eslam
Eslam

Reputation: 363

How to add a new record into an interactive grid using IG methods then set column's value using $s() api?

I am using Oracle Apex 18.2.

I have an interactive grid and a custom button to add a new row to the IG using,

apex.region("myRegionStaticId").widget().interactiveGrid('getActions').invoke('row-add-row'); then set a column's value using, $s("myColumnStaticId","2");. When I try it, it adds the first row without setting any columns' values and starts setting the value from the second row on. Even using selection-add-row or insert-record, there is always something with the first row. Here is a sample,

[https://apex.oracle.com][1]
ws = ESLAM_WS
user = forhelp
pwd = forhelppwd
app = TEST
page = Add Row on top of an IG.

Upvotes: 0

Views: 6806

Answers (3)

Clark
Clark

Reputation: 42

const
widget = apex.region("staticRegionId").widget(),
view  = widget.interactiveGrid("getCurrentView"),
model = widget.interactiveGrid("getViews","grid").model,
selection = view.getSelectedRecords(),
recId = model.insertNewRecord(undefined,selection[selection.length-1]);
model.setRecordValue(recId,'DESCR','Your Description Here');

Notes (see also Oracle Apex docs):

  • $s() didn't work for me, so different approach.
  • model.insertNewRecord takes a record - NOT a record id - to insert the new record after (as 2nd argument). It returns the newly created record-id (temporary id).
  • model.setRecordValue uses the column name, not any static-id.
  • The IG must be Edit enabled, and have 'Add Row' as an Allowed Operation.

Upvotes: 0

Dan McGhan
Dan McGhan

Reputation: 4659

After a lot of talking and testing, I've found that $s with setTimeout isn't very reliable. I've set up page 7 again to demonstrate.

  1. If you click the Rowaddrow button twice in rapid succession (the second time before the first setValue returns), the second row will not be initialized. I'll show you a workaround for this below, but you'll
  2. If you lower the setTimeout to, say, 10 ms, and try focusing in the Expiry Date column before clicking the Rowaddrow button, you'll find it doesn't work. This means that, while the setTimeout of 100 ms works now, it could break in the future if the IGs internal logic changed. Unlikely but who knows.

For the moment, I would say that $s can only be reliably used to set a column value in an IG for the active row. When the row-add-row action adds a new record, it does make it active, but that is done asynchronously via setTimeout. This is because the IG is based on the flyweight pattern and there are a number of async (setTimeout based) heuristics that are built in to handle focus and blur events to correctly enable and disable rows and cells as needed.

I've found the following to be the most reliable solution. Unfortunately, it's more complex than what you had before - but it was the only way I could wrangle it all together. Feel free to use it or not. See page 8 for an example.

Right-click the custom Rowaddrow button and select Create Dynamic Action. Set the Name of the DA to rowAddRow button clicked. The When settings will automatically be configured for the click event on the button.

Select the action for the new DA. Set Action to Execute JavaScript and enter the following JavaScript in the Code attribute.

addRowClicked = true; // Global used to distinguish custom button click
this.triggeringElement.disabled = true; // Disable button to serialize access
apex.region("KITCHEN_SHARE_DTL").widget().interactiveGrid("getActions").invoke("row-add-row");

Create a new Dynamic Action and set the Name to New row initialized. In the When section, set Event to Row Initialization [Interactive Grid], Section Type to Region, and Region to KITCHEN_SHARE_DTL.

Under Client-Side Condition, set Type to JavaScript expression and enter the following code in JavaScript Expression (which ensures the DA only fires for the click of the Rowaddrow button):

addRowClicked === true

Select the action for the new DA. Set Action to Set Value, Set Type to Static Assignment, and Value to 2. In Affected Elements, set Section Type to Column(s) and Column(s) to INGREDIENT_ID. This will replace the static assignment that was being done with $s. Ensure that Fire on Initialization is disabled.

Right-click the True branch for the DA and select Create TRUE Action. Set the Action to Set Value, Set Type to SQL Statement, and enter the following code in SQL Statement:

select MIN(EXPIRY_DATE) from stock
where ingredient_id = TO_NUMBER(:INGREDIENT_ID);

Set Items to Submit to INGREDIENT_ID and disable Escape Special Characters. In Affected Elements, set Selection Type to Column(s) and Column(s) to EXPIRY_DATE. Ensure that Fire on Initialization is disabled.

Right-click the True branch for the DA and select Create TRUE Action. Set Action to Execute JavaScript Code and enter the following JavaScript in the Code attribute.

addRowClicked = false; // Unset the global
$x('ADD').disabled = false; // Enable the button

Upvotes: 1

Salim Hlayel
Salim Hlayel

Reputation: 371

Change the following code:

$s("INGREDIENT_ID","2");

with the following one:

setTimeout(function(){ $s("INGREDIENT_ID","2"); }, 100);

It seems that the IG needs a little time to render the new row before you are able to change any value.

Upvotes: 0

Related Questions