How to get a value in a variable PL/SQL - oracle

I am in the realization of a form in PL/SQL also with the help of hypertext procedures (HTP), what I want is to obtain in a variable the value that I am selecting in a dropdown, the code with which I am building part of my form is as follows:
ELSIF cant_rol > 1 then
HTP.p( 'V_ROL: '|| V_ROL);
HTP.p( 'V_TERM: '|| V_TERM);
bwckfrmt.p_open_doc ('HWSKCETI.P_Principal', v_term); --
HTP.formOpen (twbkwbis.f_cgibin || 'HWSKCETI.P_Principal', cattributes=>'onsubmit="checkSubmit();"');
twbkfrmt.P_TableOpen (
'DATAENTRY',
cattributes => 'SUMMARY="' ||
G$_NLS.Get ('HWSKCET1-0000',
'SQL',
'This table allows the user to select the role') ||
'."'
);
twbkfrmt.P_TableRowOpen;
twbkfrmt.P_TableDataLabel (
G$_NLS.Get ('HWSKCET2-0001', 'SQL', 'Select a rol: ')
);
twbkfrmt.P_TableDataOpen; --
twbkfrmt.p_formlabel (
G$_NLS.GET ('HWSKCET3-0002', 'SQL', 'Rol'),
visible => 'INVISIBLE',
idname => 'role_id'
); --twbkfrmt
HTP.formSelectOpen (
'campus',
NULL,
1
);
FOR currole IN (select sorarol_radm_code
from SORAROL WHERE SORAROL_PIDM = global_pidm
AND sorarol_radm_code LIKE 'EXPT%')
LOOP
twbkwbis.P_formSelectOption (currole.sorarol_radm_code);
END LOOP;
HTP.FormSelectClose;
twbkfrmt.P_TableDataClose;
twbkfrmt.P_TableRowClose;
twbkfrmt.P_TableClose;
HTP.formsubmit (NULL, G$_NLS.Get ('BWSKFLI1-0007', 'SQL', 'Enviar'), 'id="btn_submit_role"'); --G$_NLS.Get ('BWSKFLI1-0007', 'SQL', 'Submit')
HTP.p( 'V_ROL: '|| v_rol);
HTP.formClose;
RETURN;
END IF;
The following is the view in which I am showing my dropdown and I load the different roles that I have
See example image here
But when wanting to select the value within the dropdown, the variable V_ROL is shown empty.

It's a little unclear what you're asking and your code sort of starts in the middle. But if you're using htp, then you're generating a form for a user to interact with. So if you want v_rol to have a value, you have to assign it one and you don't seem to do that anywhere.
If you want the value in the page to change in response to user action, like when the user chooses an option in the select list, that's not going to be PL/SQL, that's going to be JavaScript running in the browser.

Related

Oracle Apex Master Detail Report and Detail report with Radio Button Option to select

I am looking for advice to build a simple Quiz type application in Oracle Apex.
I don't need to build any Create/Update/Delete screens for base tables since I will populate my tables with data using SQL statements.
I have two tables
Create Table Question_Bank
(
Question_Id Number (5) Primary Key ,
Question_Description Varchar2(1000)
)
;
Question_Choice_Id is like 1,2,3,4 ( it is like no of quiz option choices)
Create Table Question_Choices
(
Question_Choice_Pk Number (5) Primary Key,
Question_Id Number(5) References Question_Bank(Question_Id),
Question_Choice_Id Number(1),
Question_Choice_Description Varchar2(200),
Is_Correct Varchar(1) Default 'N',
Explanation Varchar2(500)
);
So application should be displaying questions and options like this.
I would prefer one scrollable page of some numbers on question on one page.
This is Question No 1
Option 1
Option 2
Option 3
Option 4
This is Question No 2
Another Option 1
Another Option 2
Another Option 3
Another Option 4
This is Question No 3
Q No 3 Option 1
Q No 3 Option 2
Q No 3 Option 3
Q No 3 Option 4
So far I have created Master/Detail form which is kind of report (not editable) and I can see questions and possible choices (I have select question and choices are shown in 2nd column) but this is not what I want.
I am using Free Oracle Apex online account version 20.2.
You can try dynamicly build page with questions and choices. You have to add a new PL/SQL Dynamic Region region to page. In Source > PL/SQL Code region attribute put sample code below.
FOR l_question IN (
SELECT QUESTION_ID, QUESTION_DESCRIPTION
FROM QUESTION_BANK
order by QUESTION_ID
) LOOP
HTP.P('<h3>' || APEX_ESCAPE.HTML(l_question.QUESTION_DESCRIPTION) || '</h3>');
HTP.P(
APEX_ITEM.HIDDEN(
p_idx => 1, -- Values stored in APEX_APPLICATION.g_f01 table.
p_value => l_question.QUESTION_ID
)
);
HTP.P('<fieldset id="qfs' || l_question.QUESTION_ID || '">');
HTP.P(
APEX_ITEM.TEXT(
p_idx => 2, -- Values stored in APEX_APPLICATION.g_f02 table.
p_item_id => 'qh' || l_question.QUESTION_ID,
p_attributes => 'style="display:none"'
)
);
FOR l_choice IN (
SELECT QUESTION_CHOICE_ID, QUESTION_CHOICE_DESCRIPTION
FROM QUESTION_CHOICES
WHERE QUESTION_ID = l_question.QUESTION_ID
) LOOP
HTP.P('<input type="radio" value="' || l_choice.QUESTION_CHOICE_ID || '" name="' || l_question.QUESTION_ID || '" onchange="document.getElementById(''qh' || l_question.QUESTION_ID || ''').value = this.value">');
HTP.P('<label for="' || l_question.QUESTION_ID || '">' || APEX_ESCAPE.HTML(l_choice.QUESTION_CHOICE_DESCRIPTION) || '</label>');
END LOOP;
HTP.P('</fieldset>');
END LOOP;
This PL/SQL block iterates through all questions, then prints HTML markup with question description and fieldset with radio buttons. As you can see I use APEX_ITEM package to generate two columns - QUESTION_ID and QUESTION_CHOICE_ID. Each iteration creates new record with these two columns. If you checked the APEX documentation you may wonder why I didn't use APEX_ITEM.RADIOGROUP for building radio buttons. The trick is this procedure doesn't fit for this case, because its behaves different then developers expects. So insted of using this procedure i build radio group buttons manually. I also put simple onchange event for every input to save selected choice in every question. This event sets item in second column.
Each column is stored in collection APEX_APPLICATION.G_Fxx, where xx is between 01 and 50. There is p_idx parameter which determines index of collection for store column values. After page submit, APEX submit values in those collections. You can handle this, creating new process (Processing > Processes or Processing > After Submit) and pasting code below.
DECLARE
v_question_count NUMBER := APEX_APPLICATION.g_f01.COUNT;
v_question_answer_id QUESTION_ANSWERS.QUESTION_ANSWER_ID%TYPE := QUESTION_ANSWERS_SEQ.NEXTVAL;
BEGIN
FOR i IN 1..v_question_count LOOP
INSERT INTO QUESTION_ANSWERS (QUESTION_ANSWER_ID, QUESTION_ID, QUESTION_CHOICE_ID)
VALUES (v_question_answer_id, APEX_APPLICATION.g_f01(i), APEX_APPLICATION.g_f02(i));
END LOOP;
END;
There is another iteration through collections (both has the same number of members) and insert values into some table.
My code generates form without fancy styling, so you have to handle this yourself :)
Please take a look at the Survey Builder app, which allows users to review/preview/submit questions and answers.
This application can solve the requirement you have or give you an idea on how to build it.
You can find this application at App Gallery.

Oracle APEX -How to combine server side condition of "requet = expression1" and "exisits ( sql query return atleast one row)

I want to call validation when
query return at least one row like ( select 1 from table where id = 1 )
and
when request "add_data" is called
Don't know what to select here:
The value of request can be accessed via the bind variable REQUEST . To tackle your specific problem you could add that to your condition of type 'Rows returned' like this:
SELECT 1
FROM table
WHERE (
id = 1 AND
:REQUEST = 'add_data'
)
If you're more a fan of pl/sql you could take the condition type 'PL/SQL Function Body' with code like this:
DECLARE
l_dummy NUMBER;
BEGIN
-- quit here if request value doesn't match
IF :REQUEST != 'add_data' THEN
RETURN false;
END IF;
-- check if we have rows in table.
BEGIN
SELECT 1
INTO l_dummy
WHERE EXISTS (select 1 from table where id = 1)
EXCEPTION WHEN NO_DATA_FOUND THEN
RETURN false;
END;
RETURN true;
END;
This is more code but you could find it easier to read which can be an advantage for maintenance later on.
The way I understood it, add_data request is related to a button you push. If that's so, then - if you don't do anything, request name equals button name - so let's pretend that button name is ADD_DATA. Therefore:
in "When Button Pressed" property select button's name (ADD_DATA, right?)
in "Condition Type" pick the condition you mentioned ("SQL query returns at least one row")

Debugging and updating values in APEX Interactive report

I have two problems in my Interactive Report APEX 4.2.5 application. I have seen several examples of this functionality but they have not help me so far..
1 - In the report SELECT statement I am selecting some of the fields using apex_item.text, as I want user to be able to updated these fields. This part is working fine. My problem is with writing the updated values back to a table (the SELECT is on a view). I have a SQL Autonomous block process that is supposed to be doing this (looping through the rows and accessing values using APEX_APPLICATION.G_Fxx) but it is not working. No errors are returned after Submit, instead the values revert to original values. How can I get these updates to save in the table?
2 - Within the SQL process I have enabled and added some APEX_DEBUG.MESSAGE statements, but I do not see the result of these statements anywhere in the debug log or table. How can I see the result of these debug commands?
Here is the SELECT:
select REQUISITION_LINE_ID
,apex_item.hidden(50,REQUISITION_LINE_ID,10,10) rid
,REQ_NUMBER
,REQ_LINE_NUMBER
,REQUISITION_QUANTITY
,SO_NUMBER
,SO_LINE
,ORDERED_QUANTITY
,SKU
,DESCRIPTION
,apex_item.text(10, SUPPLY_PO_NUMBER, 10, 10) SUPPLY_PO_NUMBER
,apex_item.text(20, SUPPLY_PO_LINE, 10, 10) SUPPLY_PO_LINE
,apex_item.text(30, SUPPLY_PO_SHIPMENT , 10, 10) SUPPLY_PO_SHIPMENT
from camlb.xxcb_requisition_reference;
And here is the SQL process:
declare
id number;
poorder number;
poline number;
poshipment number;
begin
APEX_DEBUG.ENABLE(p_level => 9);
for i in 1..APEX_APPLICATION.G_F50.count
loop
id := APEX_APPLICATION.G_F50(i);
poorder:=APEX_APPLICATION.G_F10(i);
poline:=APEX_APPLICATION.G_F20(i);
poshipment:=APEX_APPLICATION.G_F30(i);
APEX_DEBUG_MESSAGE.LOG_MESSAGE('ID is ' || id || ', PO is ' || poorder || ', SUPPLY_PO_LINE is '|| poline || ', SUPPLY_PO_SHIPMENT is ' || poshipment);
APEX_DEBUG.MESSAGE('ID is ' || id || ', PO is ' || poorder || ', SUPPLY_PO_LINE is '|| poline || ', SUPPLY_PO_SHIPMENT is ' || poshipment);
update APPS.po_requisition_lines_all
set ATTRIBUTE1=poorder,
ATTRIBUTE2=poline,
ATTRIBUTE3=poshipment
where requisition_line_id=id;
end loop;
end;
Note, the checkbox array will be dense, while your text box arrays are sparse, thanks to HTML behaviour. There are a few posts out there on this topic, plus some other general checkbox processing posts https://www.talkapex.com/2009/01/apex-report-with-checkboxes-advanced/
You need to put your application in debug mode, using the developer toolbar usually found at the bottom of your runtime page (if you're also logged into the builder).
This will set the relevant URL parameter to YES. Look for the log related to the page submit, not render. It might also pay to log the relevant array counts before entering the loop.

How to pass a parameter to an Oracle Apex application process?

I'm using Oracle Apex 5. I have an ajax routine that gets a list of room numbers:
apex.server.process("getRooms"
,{pageItems:"#P1_ROOM"}
,{dataType:"text"})
.done(function(pReturn){
-- my processing code --
})
Instead of hard coding #P1_ROOM, can I pass a parameter? (I have many room number drop downs on the page.) Can I also somehow pass additional parameters, like the div id in which the form field #P1_ROOM exists?
Also, the 'getRooms' application process references the same hard coded value for the form field: :P1_ROOM. Can I parameterize this also?
declare
roomList varchar2(32000) := '';
begin
IF(:P1_ROOM)!= ' ' THEN
for c in
(select distinct room_id from RTP_PERSON_VIEW
where upper(room_id) LIKE upper(:P1_ROOM) || '%'
order by room_id)
loop
roomList := roomList || '~' || c.room_id;
end loop;
htp.prn( roomList );
END IF;
end;
Use the Apex JavaScript API syntax $v("P1_ROOM") to pass the parameter.
You can pass a maximum of 10 values like this:
apex.server.process (
"MY_PROCESS"
, { x01: $v("P1_ROOM")
, x02: $v("P1_CATS")
, x03: $v("P1_DOGS")
, x04: 'my last variable'
}
, { dataType: 'text'
,success: function(pData){alert(pData)}
}
);
Here you have more examples on how to use the Apex JavaScript API.
Here you can find a tutorial on how to pass more than 10 values with apex.server.process
There is another way:
apex.server.process (
"MY_PROCESS"
, { pageItems: "#P152_ID,#P152_ID_OBJ,#P152_ORDER_DT,#P152_SUMM" }
, { dataType: 'text'
, success: function(pData){alert(pData)}
} );

identify selected checkboxes in apex interactive report

I have an Interactive Report which I'm generating using a collection.
select apex_item.checkbox(1,'obj_name') ' ',
col 01,
col 02
from apex_collections where collection_name='XYZ';
The table on which this report is being generated has a composite primary key,
so when the user selects multiple checkboxes, I'm not able to figure out how to identify which all rows were selected by user. This is because according to my knowledge, through p_value in apex_item.checkbox(p_idx,p_value) I can just pass one column/field/item. But the requirement is to pass both obj_name and col 01 back to the pl/sql code.
To explain it better, I have an on submit process associated to it.
FOR I in 1..APEX_APPLICATION.G_F01.COUNT LOOP
DELETE FROM abc
WHERE obj_name = (APEX_APPLICATION.G_F01(i))
AND tab_col = col 01;
END LOOP;
So how can I send the value of col 01 of the selected checkboxes to the above process is what my question is. Any help would be great.
A better approach which I've found now is using rownum as unique value, that actually reduces a lot of logic in my code. Just calling it out.
Could you concatenate the obj_name and col_name?
select apex_item.checkbox(1,'obj_name-'||col_01) ' ', from apex_collections where collection_name='XYZ';
Then in the processing section
FOR I in 1..APEX_APPLICATION.G_F01.COUNT LOOP
my_object_name := substr( G_F01(i), 1, instr( G_F01(i), '-' ) - 1 );
my_column_name := substr( G_F01(i), instr( G_F01(i), '-' ) + 1 );
DELETE FROM abc WHERE obj_name = my_object_name AND tab_col = my_column_name;
END LOOP;

Resources