Oracle Apex dynamic action not firing on true condition - oracle-apex

I have a page with two Interactive Grids. One shows Approved records. One shows Unapproved records. There is a button with processing underneath on each grid to set the selected rows to Approved/Unapproved respectively.
I want to hide these buttons based on if a user is an Approver. These values are store in some user managed tables.
I have a dynamic action on Page Load that runs the following and sets a page item to 1 / null depending on the return:
select 1 from users where upper(username) = upper(:APP_USER) and userrole = 'APPROVER';
Based on the value in the page item two dynamic actions fire on page load to set the buttons with
True=Show
False=Hide.
Client Side Condition: Item = Value: P1_PAGE_ITEM = 1
Now - on my local machine this works fine. I made the page item visible. Can see a 1 or null and the buttons are hidden/shown.
I moved this to a Development environment and now I get a warning about Unsaved Changes each time I click out of the page (doesn't happen on Local). And although I can see a 1 in the Page Item field the actions see this as False (I put an alert on to fire when true/false).
Question is: Why am I getting the unsaved changes warning on the new environment. And why would the actions see the field as FAlse.
I have compared all of the properties as best as I can and they seem identical. I have even arranged the sequence numbers to be identical in the two environments.
All thoughts welcome...

This doesn't need to be a DA that is modifying a field value, hence the alert.
Why not define a computation that executes during the render, and use that as a server side condition on your Dynamic Action?
Otherwise you've enabled a security threat, where the user can tweak some HTML to see the regions you've hidden.

Related

Pass values between pages Oracle APEX

There is a problem transferring values between pages in the application. I have 2 pages on the first page there is a variable P9_ITEMID (when you run page 9, in this variable SQL Statement query writes the data). There is a second page 181. I want to move data from variable P9_ITEMID to variable P181_ITEM. To do this, I use the 'redirect to page in this application' option. But it doesn't work. Although I see in the variable P9_ITEMID there is data. But when you go to page 181 but P181_ITEM is empty. I would be grateful for help))
P9_ITEMID is a virtual variable that is not assigned to any column in the table. This mmin simply displays data. When I start the page, I see the data that was written to it due to the dynamic action
also i tried to write the value in P9 ITEMID this way
My code:
declare
v_empname items.id%type;
begin
select id into v_empname
from items where id = :P9_ITEMID;
apex_util.set_session_state('P9_ITEM_ID', v_empname);
exception
when others then
apex_util.set_session_state('P9_ITEM_ID', null);
end;
I'm assuming that you have created a button with action: 'redirect to page in this application' and you want the session value of a page item to be passed to the target page.
When an url is constructed using link builder, the link is built at page rendering time. It does not pick up any changes in session. Even when you set the session state in a dynamic action, it will not pick it up because the url is already rendered.
To pick up any changes on that page, it is necessary that the page item value is set in session state and this is done by the "page processing".So if you use "Submit Page" on the button and create a branch to redirect to the page it will behave the way you want.

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.
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.
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
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
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.

Oracle APEX - Transferring page item value from one page to another

Not sure what am I doing wrong and need help to diagnose the issue.
I have an apex page with an IG on it with radiobutton selection column, allowing the user to select only one row at a time.
On row select I use javascript to grab the ID of the selected row and then use Execute PL/SQL
NULL;
in order to store the value into the session state of P2_ID.
I also have a button on the page that has another page as a target - page 3, and I need to get my P2_ID value to that page.
So I set the page item of a target page - P3_ID ro &P2_ID. in a Link Builder - target pop up window. Along with that I pass another page item P2_TEST, which has a static value.
Now when I get to page 3, I do not see P3_ID in the session state while I do see P3_TEST and it does have a value, but P3_ID is not even listed... What am I doing wrong here?
How about this: instead of executing NULL; when pushing the button, SUBMIT (submit will certainly store values into session state). Create a branch which takes you to page 3; among branch properties, you'll find an option to set P3_ID to P2_ID

Updating values, one control to another

History, I am an experienced PL/SQL dev learning to use Apex and struggling with some of the concepts. Before working with PL/SQL I worked with various platforms including Delphi and VB.
Problem, how to pick up the value set in component from another component. The object of the exercise is to make the report in an interactive grid change dependant on a value selected in a drop down, the value in the drop down being in the where clause as a bind var. My original setup for this did not work. After various experiments with this I produced this test case where the object is for the label to display the value selected in the drop down:-
Page view
P300_SELECT (left) is a simple drop down, unmodified with the default values. P300_SELECTED_VALUE is a label set to display the value in P300_SELECT:-
Component setup
This does not work! And it continues not to work when I change the source setup of the label to be STATIC VALUE and set the value to &P300_SELECT.
I have also tried adding a CHANGE dynamic action on the drop down to call refresh on the label, it still does not work! In desperation to confirm that the value was indeed changing for the drop down I added a second true action to the change event executing the following javascript:
apex.message.alert($v("P300_SELECT"));
Sure enough, this works showing that the event is firing and that the value is correct:-
Label no change, but alert message works...
SO WHAT IS HAPPENING?
Why does the label not update even with a refresh called on it?
What do I have to do to make this work?
Thanks in advance for your help!
Bob
To do this
1 - Create one dynamic action to start when you change the value of P300_SELECT.
2 - Now there is a lot of ways to do this step, but I will sugest to do in this way. Create one true action in this dynamic action, this true action is "Execute PL/SQL code". The code is:
BEGIN
:P300_SELECTED_VALUE := :P300_SELECT;
END
In this true action put the item P300_SELECT in the field "Items to submit". And the item P300_SELECTED_VALUE in "Items to Return".
3 - Now create one more true action in this same dynamic action. This true action is "Refresh" and select the region of your report/IG.
***If the item P300_SELECTED_VALUE is just to test, so discard the first true action above and fill the field next of your select statement "Page items to submit" with the item P300_SELECT.
Why what you have try don't work?
1 - The source section is used to set the value when the page is loaded, this setup not affect changes after the page is loaded.
2 - The report is not refreshed because the item is not in the session after you change it.
Ex. https://apex.oracle.com/pls/apex/f?p=145797:15
Use this workspace to check something:
workspace: STACKQUESTIONS
user: test
password: test
app: 145797
page: 15
login on: https://apex.oracle.com/pls/apex/f?p=4550

"general" variable in oracle apex

I'm developing an application in Oracle Application Express (APEX).
First page contains list of projects as a tabular report.
Clicking any of the rows forwards to the next page, where records can be edited. I've implemented it with following settings:
Link column: link to custom target
Target: Page in this application
Until this is fine.
My problem is how to pass actual report to the next page?
My table, which is the basis of the report has primary key (ID), and also owner & title combination is unique. Currently ID column is not included in the report.
Also the second page doesn't currently contain field showing ID, as this information isn't important to the users.
I know I could set ID column in report, and create a read only (even hidden) text box in the next page, however I'm looking for a more elegant solution. What is the standard way to solve this?
I wonder if you are asking: "How do I pass a value from page 1 to page 2 so page 2 can use the value to do a query and present the results. If so, here is how it's done.
On page P1, the report, for example, select the attributes for the report region under the region in the Rendering pane on the left of the page designed.
Under Attribute Properties on the right side, look for Link Column and set it to "Link to custom target". Then click Target.
Select the page and then in the Set Items section, on the left, under name, select the PK ID field to receive the passed value ex: P2_ID. On the right under Value select the field to pass the value, ex: #P1_ID# and click ok.
Now, when the link on page 1 report is clicked, the P1_ID is saved into Session state by Apex and passed to P2 which then performs a FETCH using the passed value.
You can read more about Session State here. Also, be aware there are security settings which affect what params can and can't be passed in the URL.
Clicking "Session" in the developer toolbar will enable you to see the session variables being passed.
If you mean "How do I store values in the app that can be accessed anywhere in the app - like a global variable" Then look at Application Items.
As always, please include version numbers in these posts.
When you create a target page let's say Page 3
And you create some items, let's say P3_ITEM_1,P3_ITEM_2, etc
You can assign values to each of them through the url in the original page
The complete APEX URL Syntax looks like this:
http://apex.oracle.com/pls/apex/f?p=AppId:PageId:Session:Request:Debug:ClearCache:Params:ParamValues:PrinterFriendly
Let’s take a closer look:
http:// – the protocol, can be http or https
apex.oracle.com – your domain/host/server, whatever you want to call it. Can also be localhost.
/pls – indicates that you are using Oracle HTTP Server with mod_plsql. If you are using APEX Listener or Embedded PL/SQL Gateway this part is obsolete/missing.
/apex – the entry from your dads.conf file (this a file on your application-server or EPG where the target database is configured) – in case of EPG its just one entry pointing to localhost, in case of an OAS you can have multiple entries, each pointing to an other database
/f?p= – procedure “f” is called and parameter “p” is set to the complete rest of the string. Remember: APEX uses mod_plsql. “f” is a public procedure, this is the main entrypoint for APEX. Or you could say: “f” is APEX.
AppId – the number or the Alias of the Application
:PageId – the number or the Alias of the Page
:Session – unique Session ID, can be 0 for Public Pages or empty (then APEX creates a new Session)
:Request – a Request Keyword. This is basically free text, just a string you can specify to react in a process or region condition on. e.g. you could pass the keyword “CREATE” and have a condition on the delete button of your page saying “dont’t display this button if request is CREATE”.
In other words: use the REQUEST to control the behaviour of your page.
When pressing a button, the button sets the REQUEST to the button-value (e.g. SAVE), so that you can control the processes in the page processing (Submit) phase.
:Debug – set to YES (uppercase!) switches on the Debug-Mode which renders debug-messages and timestamps in your Browser window. This helps to detect wrong behaviour of your page or performance issues and everything else. Every other value then YES turns the Debug-Mode off
:ClearCache – you can put a page id or a list of page ids here (comma-separated) to clear the cache for these pages (set session state to null, …). But there is more: RP resets the pagination of reports on the page(s), a collection name deletes the collection, APP clears all pages and application-items, SESSION does the same as APP but for all applications the session-id has been used in.
:Parameters – comma seperated list of page-item names. Good practice is to set only those page-items which are on the page you are going to. Accepts page-items as well as application-items.
:ParamValues – comma separated list of values. Each value is assigned to the corresponding Parameter provided in ParamNameList (first value assigned to first parameter, second value assigned to second parameter, and so on…).
The trick here is not having values which contain either a comma “,” or a colon “:”. Both would lead to side-effects and errors, as APEX gets confused when parsing the URL. Using a comma works, if enclosed by slashes: e.g. \123,89.
:PrinterFriendly – set to YES (uppercase!) switches the page into PrinterFriendly-Mode, uses the Printerfriendly template to render the Page. You can also hide regions or other elements in PrinterFriendly-Mode using the PRINTER_FRIENDLY variable in a condition.
In your case you'd use Params:ParamValues like this:
P3_ITEM_1,P3_ITEM_2:someValue_1,someValue_2
Documentation