How to display and update the records I have added/insert in the Apex interactive report - oracle-apex

I've created an interactive report to add/update/delete employee info records in custom db table.
My end user requirement is upon entering the employee number in the EMPNO field, all the details from the oracle standard table such as employee name, marital status, gender, bday must be auto generated in the form and they will only manually input the location name and mode of exit.
Now I created 3 pages: 1.home page, 2.add page, 3.update page
On page 1 (home page)
I have here the select SQL
with checkbox
On page 2 (add page),
In the page processing portion
I have
EventAddRecord
Source: db , plsql code
Here's my sample code:
BEGIN
INSERT INTO EMPINFOTBL
(PERSON_ID,
EMPLOYEE_NUM,
EMPLOYEE_NAME,
MARITAL_STATUS,
BDATE,
GENDER,
LOCATION_NAME,
MODE_OF_EXIT
)
VALUES
(SELECT PERSON_ID FROM
PER_PEOPLE_X WHERE EMPLOYEE_NUM = :P2_EMPLOYEE_NUM),
(SELECT EMPLOYEE_NUMBER ID FROM
PER_PEOPLE_X WHERE EMPLOYEE_NUM = :P2_EMPLOYEE_NUM),
(SELECT FULL_NAME FROM
PER_PEOPLE WHERE EMPLOYEE_NUM = :P2_EMPLOYEE_NUM),
(SELECT MARITAL_STATUS FROM
PER_PEOPLE WHERE EMPLOYEE_NUM = :P2_EMPLOYEE_NUM),
(SELECT DATE_OF_BIRTH FROM
PER_PEOPLE WHERE EMPLOYEE_NUM = :P2_EMPLOYEE_NUM),
(SELECT GENDER FROM
PER_PEOPLE WHERE EMPLOYEE_NUM = :P2_EMPLOYEE_NUM),
:P2_LOCATION_NAME,
:P2_MODE_OF_EXIT
);
END;
Buttons
SAVE with dynamic action
When click add button if True submit page
Now my problem is how to do the update when I click the check box,
I want my record to be displayed in the form because currently when I click the check box the form is null

To create a new record (using Page 2), you'd create a select list item which is based on per_people table; you'd display any information you want, but you'd return employee ID:
select full_name as display_value,
employee_num as return value
from per_people
order by full_name;
After selecting desired person, enter values into P2_LOCATION_NAME and P2_MODE_OF_EXIT items. When you hit the "Save" button (which submits the page), run the process (I modified what you wrote; should be way simpler):
INSERT INTO empinfotbl (person_id,
employee_num,
employee_name,
marital_status,
bdate,
gender,
location_name,
mode_of_exit)
SELECT person_id,
employee_number,
full_name,
marital_status,
date_of_birth,
gender,
:P2_LOCATION_NAME,
:P2_MODE_OF_EXIT
FROM per_people
WHERE employee_num = :P2_EMPLOYEE_NUM;
As of updating existing values: I'd again suggest you to use the Wizard as it creates everything you need - form page is based on empinfotbl table, while "Edit" button in Interactive report sends the ID value to form page whose pre-rendering process fetches data related to employee identified by passed ID.
If you created your own page, you'll have to do it all yourself.
You said:
I want my record to be displayed in the form because currently when I click the check box the form is null
Form items are empty because Apex didn't know what to fetch. As I said: pass ID value, create pre-rendering process. Or start over with the Wizard (I prefer that option).

#Littlefoot has given a perfect answer already, here are just some extra steps that might guide you to a solution (it's the "or start over with the wizzard" piece from Littlefoot's answer). I'd suggest looking how apex generates its pages when you do it out of the box. Just for testing, follow these steps
Create a new page of type "Interactive Report" and make sure to check the "Include Form Page" attribute
Give the form page a name and select "PER_PEOPLE" as table/view name
In the 2nd page of the dialog, select the primary key column of PER_PEOPLE: person_id
Click "Create Page"
You now have a working form and report that you can further customize to your specific requirements. It should give you a good idea of how a form and a report is generally configured in APEX and it saves you a ton of time
Notices how in the report page:
The edit link has the form page as target and passes the id
The CREATE button has the form page as target without the id
In the form page
No custom code is needed to initialize the form data for the current record. Instead the native process of type "Form - Initialization" is used.
No dynamic actions are used to perform the inserts - for a form that is a bad practice. Avoid it.
No custom code is needed to perform the inserts or update. Instead the native process of type "Form - Automatic Row Processing" is used.
Study these pages and apply similar logic to your own pages. It'll be a better app.

Related

Oracle Apex Dynamic action not working for form items

I have a form with items P1_APP and P1_USER.
P.S. P1_USER is select list.
Display John
Return 1
Display Andy
Return 2
I need to disable when user selects John.
When P1_USER = 'John', P1_APP should get disabled which is a multi select list.
I created dynamic action on P1_APP, True Action= Disable,Affected element P1_APP
Client condition : Item =Value
Item= P1_USER
Value= John
However this is not working.
I have used similar logic to disable interactive grid items and was able to do so. Why is this not working for form?
EDIT: In Value now i am putting 1 which is return value for John.
However when i select John. It disables P1_App upon clicking. But remains disabled even when i choose Andy.
This works for me using the following configuration.
Create form and report on EMP - everyone has access to that sample data, it is a good idea to post questions based on that.
In the form P3_DEPTNO is a select list with source
SELECT d.dname, d.deptno FROM dept d
Add a page item to my form P3_APP. This is a select list with "Allow multi selection" enabled. Select list has 2 static values.
Create a dynamic action on change of P3_DEPTNO.
Client side condition: Item = Value
Item: P3_DEPTNO
Value: 30 (note that this is the return value for SALES, not display value)
add true action of "Disable", affected item P3_APP
Click true action and select "Create Opposite Action". Save.
When I run this it work. Selecting SALES in the select list disables the item P3_APP and selecting something else enables it.

Reselect item on Select2 multi-value select list

I use plugin Select2 on Apex.
I have scenario like this:
I have three tables: ROOM, MASTER_STUDENT and MAP_STUDENT_ROOM
One ROOM can have many STUDENT
User can select more than one student(with Select2 from MASTER_STUDENT) when create ROOM
When user edit ROOM, previously selected student show in Select2 item(selected item by MAP_STUDENT_ROOM), so user can remove or add more Student
How to achieve point number 4, item Select2 list of values is MASTER_STUDENT but with default selected by MAP_STUDENT_ROOM?
I found this documentation, but i dont know how to apply it.
I'm not familiar with the Select2 plug-in.
Have you considered using the built-in Popup LOV, which since APEX 19.1 now allows multiple selection.
Whether you're using the Select2 plug-in or the built-in Popup LOV, the issue will be the same. You have a form on ROOM, that's trying to take into account an item that isn't part of the ROOM table (its values are stored in MAP_STUDENT_ROOM). The trick is to populate the item correctly during page load so that the item can correctly display the currently assigned students.
How is the item's Source configured? If it's not, set Type to SQL Query (return colon separated value). Assuming you have a primary key item on the page for the room (e.g. P1_ID), enter a query like the following:
select student_id
from MAP_STUDENT_ROOM
where room_id = :P1_ID
Then set Used to Always, replacing any existing value in session state.
This should get the item to display correctly when the page loads. However, you'll still have to figure out how to map the values back to the MAP_STUDENT_ROOM table correctly when the page is submitted. You'll need to add some logic that first deletes rows from the room (P1_ID) that are not in the selection (e.g. P1_ASSIGNED_STUDENTS). You can use APEX_STRING.SPLIT_NUMBERS to help:
delete from map_student_room
where room_id = :P1_ID
and student_id not in (
select column_value
from apex_string.split_number(:P1_ASSIGNED_STUDENTS, ':')
)
Then you can insert rows that are in the selection but not already in the room.
insert into map_student_room (
room_id,
student_id
)
select :P1_ID,
column_value
from apex_string.split_number(:P1_ASSIGNED_STUDENTS, ':')
where column_value not in (
select student_id
from map_student_room
where room_id = :P1_ID
)
I've not tested any of this code, but it should get the points across.
Another option would be to use an Interactive Grid instead of a list of values item. This is a classic master/detail scenario where students could be added and removed below the form region (typically only done after create).

How to prepopulate date field based on other date field?

I have 2 date fields in oracle apex, Date1 is mandatory needs to be input by user and Date2 needs to prepopulate as (Date1+2 years) then user clicks the save button to save the values in database.
Then, if user clicks Date2 and change to something else, it should take that value and save.
Eg:
1.User inputs Date1 - 02/07/2019
2.Date2 should automatically populate as - 02/07/2021 but should not be saved in database.
3.User clicks save button to save data.
4.User wants to change Date2 to - 05/10/2019
5.User clicks save to save data.
I tried to set value using dynamic action for step2, but step4 is not working whenever I click save button, it's recalculating back to Date1+2 years.
Please help.
Suppose you have P1_ID (primary key), P1_DATE1 and P1_DATE2 on your form.
Create a dynamic action to set value of P1_DATE2 on change of P1_DATE1. Use PL/SQL Expression as type and PL/SQL Expression
ADD_MONTHS(TO_DATE(:P1_DATE1,'DD/MM/YYYY'),24);
Set "Fire on initialization" to false so it won't recalculate P1_DATE2 when the screen loads for an existing record - that might be the cause of the behaviour you're seeing.
It makes sense that you only want the dynamic action to fire for a new record so you could add a server-side condition in your dynamic action of "ITEM IS NULL" for item P1_ID.

How to save and return to newly created item in previous page?

I have an interactive report and a form associated to it. After creating a new entry using the form, my end-users want to put the focus on that specific new entry in the interactive report (it's a lot of entrys, and today they need to scroll down a lot to see the new one).
They also want the same funcionality when updating a row of the report.
How can I do this the correct way in APEX 5.1?
Here is one aproach based on EMP table in apex.oracle.com Create interactive report with edit form. In my case this is page 6 for report and page 7 for edit. Create one hiden item on page six (P6_EMPNO). Add case to your query so in my example it's look something like:
select "ROWID",
"EMPNO",
"ENAME",
"JOB",
"MGR",
"HIREDATE",
"SAL",
"COMM",
"DEPTNO"
from "#OWNER#"."EMP"
ORDER BY CASE WHEN EMPNO = :P6_EMPNO THEN 1 ELSE 2 END, EMPNO
I'm sorting result by EMPNO.
Choose P6_EMPNO in Page Items to Submit section. Go to page 7, select branch(Go to page 6)and click on Target In set items section choose P6_EMPNO and for target &P7_EMPNO.
Now every time you go to page 7, the value of hiden item will be the EMPNO from page 7 and it will apear on top of the region. You can use jQuery to highlight the row and put some validations to update P6_EMPNO only when some data was changed.
I hope this can help you.
easy.
You don't even have to create any additional page items. Change your form DML so that it returns into the primary key page item holder. Then Create a process after your DML process but before the reset cache process. Use APEX_IR API to reset pagination on your IR page, and then set an interactive report filter based on the primary key page item you returned the new PK into. Check the documentation for exact usage.
Apex_IR.reset_report to reset the report pagination and remove any filters.
Apex_ir.add_filter to add a filter = to new primary key
Interesting question, another solution:
Create a item in your report page, something like P3_ANCHOR
Add data-anchor="#< YOUR_COLUMN_ID >#" to your report link attribute
Configure your form page to return the created/modified item id to item P3_ANCHOR in your report page.
Create a Dynamic Action on report page
Action: Execute Javascript Code
Code:
var container = $('body'),
scrollTo = $('[data-anchor="'+$v('P3_ANCHOR')+'"]');
container.animate({
scrollTop: scrollTo.offset().top - $(document).scrollTop()
}, 2000);
Simple solution:
Sort your report descending so that the last created ID will be the first in the IR

Trigger a process (SQL update) when leaving an APEX page

This is a very odd question but i wondered whether it was possible to trigger a process that runs an SQL UPDATE when the user leaves this specific page, either by clicking on the breadcrumb, tabs or back button?
I did setup the process to run on the 'Back' button; however i ran into the problem of: What if s/he clicks on the breadcrumb or a tab instead.
I have searched the net and posting this question was a last resort. I wondered if anyone can point me in the correct direction?
UPDATED POST
Page 1:
Includes a text field and a button. The user enters the category into the text field and clicks on the button to proceed to the next page. The button passes the value in the text field to a text field on Page 2.
Page 2:
Two regions on the page. One region holds information about the category - Category name from the previous page, category description, and the category revision number (which is what i'm trying to get working). The second region is a report that pulls the item name and number that are listed under the category in the category text field. A 'View' link is used on the report to load the edit page for the specific item selected. The 'View' link passes the 'category name' (from the category text field) and the 'item number' from the report to page 3.
Page 3
Two regions are used, first region: Lists the Item number which came from page 2 and name of the item (which i use a simple query to retrieve). In the second region: A report is used with two columns: a list of item properties in column 1, and a text field next to each item property in column 2 to hold the value that can be updated. The 'Apply Changes' button has some PlSql behind which looks for changes and updates where required. It updates the relevant fields that have changed, and it then takes the user back to Page 2 (Page showing user the items listed for the category intitally entered).
I cant increase the category revision on the 'apply changes' button on page 3 because the user may complete edits for items under the same category. So i dont know where i can increase the category revision by 1 per vist to a category. P.s I already increment the revision number for each item by 1 if the info has been changed using the 'apply changes' button on page 3.
One way of doing this is by updating the session state of the page items (without submitting the page as normal) via ajax and by calling an Application Process which updates the table, when called by a javascript onbeforeunload.
Create an Application Process to fire On Demand, named UpdatePageXOnExit or something. In the PL/SQL block of that Application Process, use SQL update commands with the item state of each item on the page that you wish to update; something like the following:
BEGIN
UPDATE table_name SET col1 = :PX_ITEM_1, col2 = :PX_ITEM_2, col3 = :PX_ITEM3, col4 = :PX_ITEM_4, col5 = PX_ITEM_5
WHERE (condition... I would suggest ROWIDs to simplify changes to the
fields of the PK; otherwise you will have to create additional
page items for each field of the PK, then set those items to
the values of the PK when the page loads using a before
header page process, and then use those values in this where
clause like this: where col1 = :PX_ORIGINAL_PK_FIELD_1 AND col2 =
:PX_ORIGINAL_PK_FIELD_2 );
END ;
Go to the page settings for that particular page, and in the JavaScript: Execute On Page Load section, write something like the following:
window.onbeforeunload = updateOnExit;
And in the JavaScript Function and Global Variables Declaration, write something like the following:
function updateOnExit() {
var get = new htmldb_Get(null,&APP_ID.,'APPLICATION_PROCESS=UpdatePageXOnExit',&APP_PAGE_ID.);
get.add('PX_ITEM_1',$x('PX_ITEM_1').value)
get.add('PX_ITEM_2',$x('PX_ITEM_2').value)
get.add('PX_ITEM_3',$x('PX_ITEM_3').value)
get.add('PX_ITEM_4',$x('PX_ITEM_4').value)
get.add('PX_ITEM_5',$x('PX_ITEM_5').value)
gReturn = get.get();
get = null;
// Comment out the following line or not, as per the note in the following paragraph
return 'Are you sure you would like to leave the page?';
}
This last piece is the AJAX that updates the session states of the page items on the page that have been changed on the user's end but that haven't been uploaded to the servers end which normally occurs during page submission. Note: If you comment out the return statement, than there will be no warning box that will allow the user to stay on the page. If that is what you prefer, go for it. If you chose to use the warning box, the ajax will execute the page process even if the user chooses to stay on the page.