Navigation menu access control through DB - Apex oracle - oracle

I have a table with Page and its page numbers stored in it. I want to show only those bars on the navigation menu whose page numbers are assigned to the end user. How can I do it?
I'm using Apex 19.1

Create a function which returns a Boolean, saying whether certain user can (or can not) access certain page, e.g.
create table t_access as
select 1 page_no, 'LITTLE' app_user, 'Y' yn from dual union all --> can access page 1
select 2 page_no, 'LITTLE' app_user, 'N' yn from dual; --> can NOT access page 2
create or replace function f_access(par_page_no in number, par_app_user in varchar2)
return boolean
as
l_yn t_access.yn%type;
begin
select a.yn
into l_yn
from t_access a
where a.page_no = par_page_no
and a.app_user = par_app_user;
return l_yn = 'Y';
exception
when no_data_found then
return false;
end;
Use that function in navigation list entry's conditions property; make it a "PL/SQL function body returning a Boolean" as
return f_access(1, :APP_USER);

Related

How to conditionally render fields in oracle apex?

I'm trying to create a form that updates a table, but it should be in such that, only those fields that the admin wants to update appear in the form on the next page.
Suppose we choose a row with the id 1 to update,next the admin should be able to choose the fields he wants to update.
One option is to create a table which contains that page item names (e.g. P1_ID, P1_NAME, P1_ADDRESS, ...) and a column which says whether it'll be rendered or not (let's call it CB_RENDER). Admin would update that table and decide whether to render an item (and set cb_render = 1) or not. Table contents would then be
ITEM_NAME CB_RENDER
---------------- ---------
P1_ID 1
P1_NAME 1
P1_ADDRESS 0
Create a function which accepts item name as argument and returns cb_render value:
create or replace function f_render_item (par_item_name in varchar2)
return number
is
retval number;
begin
select cb_render
into retval
from that_table
where item_name = par_item_name;
return retval;
end;
Use that function in every item's Server-side condition; its type would be a function that returns Boolean:
return f_render_item (:APP_ITEM_NAME) = 1;
It evaluates to TRUE if function returns 1 (which means that item will be rendered).
That's all, more or less.

Redirect to page stored in table

I have an application in which a user creates a form, for which several responsible persons are selected in this form and can edit this form.
As soon as the form is submitted, the corresponding page of the process is changed.
The page of the form and the respective responsible persons are saved in a separate table.
The function has to check whether the logged-in user with the user ID is entered in the table as one of the responsibles. The table for example Responsible1 contains a foreign key to the table USERS, in which the ID is located. As soon as it finds the responsible in the table, the function then should redirect the user to the corresponding page.
create or replace function forward_user(p_username in varchar2)
return varchar2
is
l_user varchar2(255);
l_branch_page number;
begin
l_user :=p_username;
/*
Get the target page depending on entry in table
*/
select
page
into l_branch_page
from
FORM_PAGES
where EXISTS (SELECT f.RESP1 from FORM f
left outer join RESPONSIBLE1 s on s.RESP1=f.RESP1
LEFT OUTER JOIN USERS u on u.ID=s.ID where lower(u.USERNAME) =lower(l_user) )
OR (fp.RESP2 in
(SELECT f.RESP2 from FORM f
left outer join RESPONSIBLE2 p on p.RESP2=f.RESP2
left outer join USERS u on u.ID=p.ID where lower(u.USERNAME) =lower(l_user) ))
OR (fp.RESP3 in (select f.RESP from FORM f
left outer join RESPONSIBLE3 e on e.RESP3=f.RESP3
left outer join USERS u on u.ID=e.ID where lower(u.USERNAME) =lower(l_user) ));
return APEX_PAGE.GET_URL(p_page =>l_branch_page);
exception
when no_data_found then
/*Use current page as default page*/
return APEX_PAGE.GET_URL(p_page =>1);
end ;
I then call this function in a pl/sql process when the button NEXT is clicked.
DECLARE
x varchar2(4000);
BEGIN
x:=forward_user(:session_user_name);
END;
I have already checked the sql statements and they work fine, I get the corresponding page.
As well the function compiles successfully.
But when I click the button nothing happens, the user is not forwarded to the stored page in the table.
As well I tried to call this function in a branching process with the behaviour Function Returning a URL(Redirect) but as well nothing happens.
Can someone help me here?
My suggestion would be:
create a hidden page item (as you're on Page 1, let's call it P1_URL)
you already have a process which runs when the Submit button is pressed. Its execution point should be "Processing". Rewrite the process so that it populates P1_URL, e.g.
declare
l_branch_page number;
begin
-- your query goes here; I'll redirect to page 4
l_branch_page := 4;
:P1_URL := APEX_PAGE.GET_URL(p_page => l_branch_page);
end;
create an After Processing branch (why? So that process (see above) first populates P1_URL item). Its behavior's type should be "Page or URL (Redirect)", and its target should be &P1_URL. (literally that - ampersand followed by P1_URL followed by dot).
That's all; when you push the Submit button, process will populate P1_URL item which will be used by the branch and redirect to desired page. Will it work? It worked for me, I've just tested it.
Function:
function forward_user (p_username in varchar2)
return varchar2
is
...
return apex_page.get_url(p_page => l_branch_page);
end;
Process: just one line:
:P1_URL := forward_user(:session_user_name);

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")

how to make the output from checkbox to select statment?

I am currently using apex 19.1. I have this problem where I can't (or don't know how to) select certain columns from checkbox meaning I have this checkbox
which gives me the ability to check the columns names I want to use that output (:P3_COLUMN) from the check box to select a specific columns in a table. My solution was :
select :P3_COLUMN
from INPUT_TABLE$
I also tried :
select case :P3_COLUMN when 'currency' then currency when 'nationality' then nationality end as test from input_table
which gave me this output
and
DECLARE
str varchar2(100);
BEGIN
str := 'select ' || replace(:P3_COLUMN, ':', ',') || ' from input_table';
execute immediate str;
END;
which gave me this error
I don't know what to do, any help will be really appreciated.
Here's a walkthrough (my page is #51). Suppose that we want to display some column from Scott's DEPT table.
create a region whose type is classic report
create a page item (let's call it P51_COLS which is a select list item; its source is a query which looks like this:
select column_name d,
column_name r
from user_Tab_columns
where table_name = 'DEPT'
Page action on selection should be "Submit page"
region's source should be a PL/SQL function body that returns a SQL query and look like this:
return 'select case when :P51_COLS = ''DEPTNO'' then to_char(deptno )
when :P51_COLS = ''DNAME'' then dname
when :P51_COLS = ''LOC'' then loc
end as result
from dept';
Its "Page items to submit" should be set to P51_COLS
That's it ... run the page; select any column from the select list item and the result should be displayed.
Yes, I know - the query itself looks stupid as you have to name all cases. For some reason, Apex expects literally return 'select ...' statement. Concatenation, replace function, ... won't work. Perhaps someone knows why or - even better - can demonstrate how to workaround it. Meanwhile, try what's been written above.
first option use server side condition on the columns.
second option use dynamic sql> create function returns sql statement> call the function in your region source.

Changing a 0 or 1 value to "Yes" and "No" in APEX report

I have a report region on my page and it's getting data from a students table. Within that table, there's a column called cv_lodged which is either 1 or 0 representing Yes or No. In the report it shows this columns data as 0 or 1, I want to change it to show Yes or No.
How can I do this?
You can put a CASE statement in your query
SELECT (CASE WHEN cv_lodged = 1
THEN 'Yes'
ELSE 'No'
END) cv_lodged,
other_columns
FROM students
If this is something that is likely to be common, you're probably better served creating a function that converts your pseudo-boolean data to a string. Something like
CREATE FUNCTION my_bool_to_str( p_num IN NUMBER )
RETURN VARCHAR2
IS
BEGIN
IF( p_num = 1 )
THEN
RETURN 'Yes';
ELSE
RETURN 'No';
END IF;
END;
that you would call in your query
SELECT my_bool_to_str( cv_lodged ) cv_lodged,
other_columns
FROM students
I've usually just created a static LOV in Shared Components called YES1_NO0, with 2 entries: 'Yes' -> 1, 'No' -> 0.
In Interactive Reports you can then change these columns. To do this, edit the column of the IR. Change 'Display Type' to 'Display as Text (based on LOV, escape special characters)'. Then under 'List of Values' set 'Column Filter Type' to 'Use Named List of Values to Filter Exact Match' and select the named LOV.
But sure, you can totally do this in SQL.
Currently, there is a simpler way to do this.
First open the APEX page with the "Yes/No" item as developer and click on the item to open the page item settings.
Change the Settings value from Use component settings to Custom.
Afterwards change the Yes Value to 1 and the No Value to 0.
This solution has some advantages:
No need to decode the value 1 or 0 to Y or N (select decode(mycolumn, 1, 'Y', 'N') from mytable where id = 123;) or select case when ...
No need to decode the submitted value back to 1 or 0 from Y or N

Resources