Sunday, September 28, 2025

How to add screen in your favourite list (Part 2)

In the first part, we explored how to quickly add screens to your Favourite List for faster navigation. Now, in Part 2, we’ll dive deeper and extend the functionality—making it even smarter and more user-friendly. This continuation will help you maximize productivity while managing complex applications with thousands of menus. If you not explore the part one then please follow it first from here (Part 1).

You can follow below tutorials for better understanding. 

Part 2 and Part 1 from here.

Let's walk through the implementation process of part 2 step by step-

Step-1 :

Open your application and navigate to shared components. Under "Navigation and Search" section, click on "Navigation Bar List". A new page open. Click on the "Navigation Bar" link column titled "Name". Click on "Create Entry" button. A new page open. Set the below properties as like below-

Sequence: 8

Image/Class: fa-bookmark

List Entry Label:  

Target Type: URL

URL Target: #

After setting the above properties click on the "Create List Entry" button. This will create a navigation bar list in your application which will displayed in the navigation.

Step- 2:

Go back to your application builder home page and open page 0. Create a new region and set it propertise as like-

Name: Bookmarks

Type: Dynamic Content

PL/SQL Function Body returning a CLOB: Click on the code editor icon. A code editor window opened. Paste the below code here-

        DECLARE

            l_clob      CLOB;

        BEGIN

           l_clob  := '<div id="bookmark-list" onmouseleave="hideBookmark()"><ul>';

    

            FOR i IN (

                SELECT b.bookmark_id

                    , b.page_id

                    , aap.page_name

                    , LOWER(aap.page_alias) AS page_alias

                FROM bookmark b

                    , apex_application_pages aap

                WHERE 1                = 1

                AND b.page_id          = aap.page_id

                AND aap.application_id = :APP_ID

                AND b.user_id          = :USER_ID

                ORDER BY b.bookmark_id

            ) LOOP

               l_clob := l_clob||'<li><a href="http://localhost:9090/ords/r/hr/tutorial/'||i.page_alias||'?        session='||apex_application .g_instance||'">'||i.page_name||'</a></li>';

            END LOOP;

            l_clob := l_clob||'</ul></div>';

            RETURN l_clob;

        END;

Template: Blank with Attributes

Static ID: bookmark-container


Step- 3:

Select the region titled "JS 2" and navigate to properties section. Scroll down till "Header and Footer" section. Open "Header Text" code editor and add the below line of code under the success attribute.

    apex.region('bookmark-container').refresh();


Create another 2 JavaScript function here to show and hide the added favorite lists menu. Paste the below code here-

 function showBookmark() {

        var list = document.getElementById('bookmark-list');

        list.style.right = 0;

        list.style.position = 'fixed';

        list.style.top = '80px';

        list.style.borderRadius = '0px';

        list.style.backgroundColor = 'lightgray';

        list.style.zIndex = 5000 ;

    }

    function hideBookmark() {

        var list = document.getElementById('bookmark-list');

        list.style.right = "-5000px";

    }


Create another JavaScript function here to check the screen is already added into the bookmark lists or not. Paste the below code here-

    function isAddedToBookmark() {

        var userId = apex.item('P0_USER_ID').getValue();

        var pageId = $v('pFlowStepId');

        apex.server.process(

            'CHECK_BOOKMARK_ADDED' ,

            {

                x01: userId,

                x02: pageId

            } ,

            {

                dataType: 'json',

                success: function(pData) {

                    var bkmrk = document.getElementById('bookmark');

                    if (pData[0].ADDED === 'Y') {

                        bkmrk.innerHTML = '★ Remove Bookmark';

                        bkmrk.style.backgroundColor = 'red';

                        bkmrk.style.color = '#fff'

                    } else {

                        bkmrk.innerHTML = '★ Add to Bookmark';

                        bkmrk.style.backgroundColor = '#ccc';

                        bkmrk.style.color = 'black' 

                    }

                }

            }

        )

    }


Click OK.

Step- 4:

Click on "Shared Components" icon immediate before the save button. Then click on the "Navigation Bar Lists" menu under the "Navigation and Search" section. Click on "Navigation Bar" link to edit. Click on "name" column value in associate with sequence no. 8 (If you use lower version of APEX then you can find a pencil icon for editing purpose).


A new page will be appeared. Set the below properties as like-

Attributes: onclick="showBookmark()"


Click on Apply Changes.

With these enhancements, the Favourite List feature becomes more powerful and adaptable, ensuring seamless access to frequently used screens even in large applications. By combining simplicity with efficiency, this solution continues to reduce navigation time and improve overall user productivity.
















Friday, September 26, 2025

How to add screen in your favourite list (Part 1)

Tired of scrolling through menus to find the screen you use every day? There’s a smarter way! By adding screens to your favorite list, you can open them instantly without wasting time.

Managing frequently used screens becomes easier when you add them to your favorite list. This feature helps you reduce navigation time and improve efficiency by keeping your most important screens just one click away. In this article, we’ll explain the step-by-step process to add any screen to your favorites. 

If you need any visual assistance then please have a look from here.

Step- 1:

Open page 0 and add a static content region, Rename it to “Bookmark”. Set it template properties is "Blank with attributes". Go to HTML code under Source section and open it. Paste the below code in the editor-

<div id="bookmark" onclick="add2Bookmark()">

    ★ Add to Bookmark

</div>


Step- 2:

Add another static content region and rename it to "CSS 1". Set it template properties is "Blank with attributes". Scroll down to "Header and Footer" section and open "Header Text" code editor. Paste the below css code here-

<style>

   #bookmark-container {

        position: relative;

        top: 80px;

    }

    #bookmark {

        position: fixed;

        top: 50%;

        padding: 15px 20px;

        font-size: 15px;

        text-align: center;

        background-color: #ccc;

        font-family: serif;

        right: -145px;

        transform: translateY(-50%);

        box-shadow: 0px 4px 6px rgba(0,0,0,0.1);

        transition: right .6s ease-in-out;

        border-radius: 30px 0 0 30px;

    }

    #bookmark:hover {

        right: 0;

        cursor: pointer;

    }    

    #bookmark-list {

        right: -5000px;

        position: fixed;

        padding: 5px;

        font-size: 15px;

        font-family: serif;

        transform: translateY(-50%);

        transition: right .6s ease-in-out;

        width: 250px;

    }

    #bookmark-list ul {

        list-style-type: none;

        margin: 0;

        padding:0;

    }

    #bookmark-list ul li {

        padding: 4px;

    }

    #bookmark-list ul li:hover {

        font-size: 18px;

    }

</style>


HTML animated button add option is done for all page. This button is autometically displays each page of the application. 

Step- 3:

Create a database table to store the favorite screen list as per user. Open sql code editor where you feel comfort (Toad/Sql Developer/SQL commands) and paste the below code-

CREATE TABLE "BOOKMARK" 

   ( "BOOKMARK_ID" NUMBER, 

"PAGE_ID" NUMBER, 

"USER_ID" NUMBER, 

"CREATION_DATE" DATE DEFAULT sysdate

   ) ;


In my case, I have set the limit of favorite list to 10. That's why I have add a flag column in my app_user table. You can also follow this step by altering your users table. Copy and paste the below code (replace your user table name instead of 'app_user')-

ALTER TABLE app_user ADD bookmark_max_limit NUMBER DEFAULT 10;

Step- 4:

Create a database function to check the added favorite list. If  maximum limit reached then you can't add anymore screen in your favorite list. Need to remove screen first from the list and then you can add new one. Copy and paste the below code in your sql editor and then compile it-

CREATE OR REPLACE FUNCTION bkmrk_max_limit(

    p_userid    NUMBER

) RETURN NUMBER

IS

    l_count     NUMBER;

    l_limit     NUMBER;

BEGIN

    SELECT COUNT(*)

    INTO l_count

    FROM bookmark

    WHERE user_id = p_userid ;

    

    SELECT bookmark_max_limit

    INTO l_limit

    FROM app_user

    WHERE user_id = p_userid ;    

    RETURN l_limit - l_count ;

END;

/

Step- 5:

Create an application item. Open share component and click on "Application Items" menu under "Application Logic" section. Click on Create button and set "Name" and "Scope" properties. In my case name is "USER_ID" and scope is "Application".


Step- 6:

Create an application process in the same saction. Click on "Application Process" menu. A popup modal dialog opened. Enter process name and set point. I use "SET USER ID" as name and "After Authentication" as point. 


Click Next. Another popup window appeared. Enter below PL/SQL code here-

SELECT user_id

INTO :USER_ID

FROM app_user

WHERE UPPER(user_name) = UPPER(:P9999_USERNAME)

AND pass_word = apex_util.get_hash(apex_t_varchar2(:P9999_USERNAME, :P9999_PASSWORD), NULL);


If you use no password encrytion method the pass only the password field otherwise use your own encryption method. I use 
apex_util.get_hash(apex_t_varchar2() method to encrypt my password. Click Next and then click "Create Process".

Step- 7:

Create another application process in the same way. Named it to "SET_BOOKMARK" and point is "Ajax Callback: Run this application process when requested by a page process". Click Next. A popup window opened. Enter below PL/SQL code here-

DECLARE

    l_bookmark_id   NUMBER;

    l_msg           VARCHAR2(300);

    l_count         NUMBER ; 

BEGIN

    SELECT NVL(MAX(bookmark_id),0)+1

    INTO l_bookmark_id

    FROM bookmark;


    IF bkmrk_max_limit(

        p_userid  => apex_application.g_x02

    ) > 0 THEN

        -- CHECK FIRST IF THE PAGE IS ALREADY ADDED OR NOT

        SELECT COUNT(*)

        INTO l_count

        FROM bookmark

        WHERE page_id = apex_application.g_x01

        AND user_id   = apex_application.g_x02;


        IF l_count > 0 THEN

           l_msg := 'Already added to bookmark.';

        ELSE

            INSERT INTO bookmark(bookmark_id, page_id, user_id)

            VALUES(l_bookmark_id, apex_application.g_x01, apex_application.g_x02);


            l_msg   := 'Successfully added to bookmark' ;

        END IF;

    ELSE

        l_msg   := 'You have reached your max limit. Please remove one first.';

    END IF;

        apex_json.open_array;

        apex_json.open_object;

        apex_json.write('MSG', l_msg);

        apex_json.close_object;

        apex_json.close_all;

END;

Step- 8:

Go to page 0 and create a new region for declaring javaScript function so that we can call it from all page. Named it to "JS 2". Set it's template as "Blank with Attributes" and scroll down to "Header and Footer" section. Open "Header Text" code editor and paste the below code here-

<script>

    function add2Bookmark() {

        apex.server.process(

            'SET_BOOKMARK'

            , {

                x01: $v('pFlowStepId'),

                x02: apex.item('P0_USER_ID').getValue()

            }

            , {

                dataType: 'json',

                success: function(pData) {

                    apex.message.showPageSuccess(pData[0].MSG);

                }

            }

        );

    }

</script>

Step- 9: 

Create a page item named "P0_USER_ID". Set it's type to "Hidden" and value protected to "No" (toggle off) in setting section. Then go to the shared component and open the application process menu under the application logic section. Edit the "SET USER ID" process's PL/SQL code. Add the below line at the last of the existing code- 

:P0_USER_ID := :USER_ID ;

Step- 10:

Create a database function which will check that the screen is already added to favorite list or not. Open SQL editor and paste the below code here. Compile the code.

CREATE OR REPLACE FUNCTION chk_bkmrk_added(

    p_user_id   IN      NUMBER

    , p_page_id IN      NUMBER

) RETURN VARCHAR2

IS

    l_count     NUMBER;

    l_return    VARCHAR2(1);

BEGIN

    SELECT COUNT(*)

    INTO l_count

    FROM bookmark

    WHERE user_id  = p_user_id

    AND page_id    = p_page_id ;

    

    IF l_count > 0 THEN 

        l_return    := 'Y' ;

    ELSE

        l_return    := 'N' ;

    END IF;

    RETURN l_return ;

END ;

/

Step- 11:

Create another application process in shared components section under the application logic sub section. The process is as same as step 6 and 7. Click on "Application Process" and then click on "CREATE" button. Enter process name and point. In my case, i use "CHECK_BOOKMARK_ADDED" as name and use point as "On Load: Before Header (Page Template Header)". In the source tab, paste the below code in the code field-

DECLARE

    l_chk   VARCHAR2(1);

BEGIN

    l_chk := chk_bkmrk_added(

                p_user_id   => apex_application.g_x01

                , p_page_id => apex_application.g_x02

            ) ;

    apex_json.open_array;

    apex_json.open_object;

    apex_json.write('ADDED', l_chk);

    apex_json.close_object;

    apex_json.close_all;

END;

/


Step-12:
Create a dynamic action in page 0. Click on dynamic action tab under the left side navigation pane. Select "Page Load" under the drop down tree menu. Right click here and select "Create Dynamic Action". A dynamic action will be created with titled "New". Rename it as per your choice. I renamed it "Check Bookmark".
Select the autometically created true action and change its properties like below-
Action: Execute JavaScript Code
Code:
        function isAddedToBookmark() {
            var userId = apex.item('P0_USER_ID').getValue();
            var pageId = $v('pFlowStepId');

            apex.server.process(
                'CHECK_BOOKMARK_ADDED' ,
                {
                    x01: userId,
                    x02: pageId
                } ,
                {
                    dataType: 'json',
                    success: function(pData) {
                        if (pData[0].ADDED === 'Y') {
                            var bkmrk = document.getElementById('bookmark');
                            bkmrk.innerHTML = '★ Remove Bookmark';
                            bkmrk.style.backgroundColor = 'red';
                            bkmrk.style.color = '#fff'
                        }
                    }
                }
            )
        }

Save the page and run the application. 

By adding screens to your favourite list, you can significantly enhance navigation efficiency and streamline your daily tasks. This simple yet powerful feature ensures that frequently accessed screens are always just a click away, helping you maintain a smooth and productive workflow. 



Thursday, September 4, 2025

How to display image without page item reference in Oracle APEX

In this section, we'll learn how to display images in our Oracle APEX application without relying on a page item. This method is perfect for situations where we need to show an image directly from a database table column, a file, or a URL without first loading it into a specific page item. We'll cover how to achieve this using a dynamic action and a PL/SQL procedure, making our application more efficient and flexible. By the end of this tutorial, we'll be able to display images dynamically, improving the user experience and reducing page load times. This technique is useful for reports, dashboards, and custom user interfaces where a static page item isn't the best solution. You can vind a visual solution from here.

STEP 1: Create a blank page.

STEP 2: Create a region and set it properties like-

        Name:                Emp

        Type:                  Interactive Grid

        Source:

            Location;        Local Database

            Type:              SQL Query

            SQL Query:    SELECT employee_id, first_name FROM employees

        Column:              3

        Column Span:     2

        Template Options:

            Header:          Hidden

STEP 3: Create a new region and set it properties like-
        Name:                 Region Container

        Start New Row:  No (Toggle Off)

        Column Span:    5

        Template Options:

            Header:          Hidden

STEP 4: Create another region for contaning some neccessary items-

    Set the below properties for this region-

    Name:                    Item Container

    Type:                      Static Content

    Template:              Blank with Attributes

    Template Options:

        Item Spacing:    Slim

STEP 5: Create page Items to display employee information in details-

        P32_EMP_ID => Set it's type hidden and value protected to no (toggle off).

        P32_NAME

        P32_DESIGNATION

        P32_DEPT

        P32_HIRE_DATE

        P32_MOBILE

        P32_EMAIL

        P32_SALARY

STEP 6: Create another region for displaying image-

    Set the below properties for this region-

    Name:                    Image Container

    Type:                      Static Content

    Start New Row:    No (Toggle Off)

    Template:              Blank with Attributes

    Template Options:

        Item Spacing:    Slim

STEP 7: Create a page item under 'Image Container' region.

    Set below properties for this item

    Name:                    Display Image

    Type:                      Dispaly Image

    Based On:              Image URL Stored in Page Item Value

    Template:               Optional

    Custom Attributes: style="border:1px solid gray;width:100px;height:100px"

    Default:

            Type:               Static

            Static Value:    ''

STEP 8: Create a dynamic action to capture the Employee Id-

    Select "Emp" region and reight click here and choose Create Dynamic Action. Set the below                    properties of this dynamic action-

    Name:                    Set Emp Id

    Leave other properties as it is. Select True action and set it properties as like below-

    Action:                   Execute JavaScript Code

    Code:                    

                                    model = this.data.model ;

                                    var i, empId;

                                    for (i=0; i < this.data.selectedRecords.length; i++) {

                                        empId = model.getValue(this.data.selectedRecords[i],'EMPLOYEE_ID');

                                        $s('P32_EMP_ID', empId);

                                    }       


STEP 9: Create Ajax Callback Process for preparing image to display

    Go to processing tab and select Ajax Callback. Right click here and Create Process. Set it properties         as like-

    Name:                    SET_EMP_DETAIL

    Type:                      Execute Code

    PL/SQL Code:       

                                   BEGIN

                                        apex_json.open_array;

                                        apex_json.open_object;

                                        FOR i IN (

                                            SELECT first_name||' '||last_name AS ename

                                                , job_id

                                                , department_name

                                                , email

                                                , phone_number

                                                , TO_CHAR(hire_date,'DD/MM/RRRR') AS hire_date   

                                                , salary  

                                                , 'data:image/jpg;base64,'||apex_web_service.blob2clobbase64(emp_photo) AS src

                                         FROM employees e

                                            , departments d   

                                        WHERE 1 = 1

                                        AND e.department_id = d.department_id

                                        AND employee_id = apex_application.g_x01

                                ) LOOP

                                        apex_json.write('ENAME', i.ename);

                                        apex_json.write('JOB', i.job_id);

                                        apex_json.write('DEPT', i.department_name);

                                        apex_json.write('EMAIL', i.email);

                                        apex_json.write('PHONE', i.phone_number);

                                        apex_json.write('HIRE_DATE', i.hire_date);

                                        apex_json.write('SALARY', i.salary);

                                        apex_json.write('SRC', i.src);

                                END LOOP;

                                apex_json.close_object;

                                apex_json.close_all;

                        END ;


STEP 10: Create another dynamic action-

    Select 'P32_EMP_ID' items and create adynamic action here. Set it's properties as like below-

    Name:                    Set Emp Details

    Select true action and set it's properties as -

    Action:                   Execute JavaScript Code

    Code:                     

                                   apex.message.clearErrors();

                                        apex.server.process(

                                            'SET_EMP_DETAIL'

                                            , {

                                                    x01: $v('P32_EMP_ID')   

                                            }

                                            , {

                                                    dataType: 'json',

                                                    success: function(pData) {

                                                        $s('P32_FULL_NAME', pData[0].ENAME);

                                                        $s('P32_DEPT', pData[0].DEPT);

                                                        $s('P32_DESIGNATION', pData[0].JOB);

                                                        $s('P32_EMAIL', pData[0].EMAIL);

                                                        $s('P32_MOBILE', pData[0].PHONE);

                                                        $s('P32_HIRE_DATE', pData[0].HIRE_DATE);

                                                        $s('P32_SALARY', pData[0].SALARY);

                                                        var img = document.getElementById('P32_DISPLAY_IMAGE');

                                                        img.setAttribute('src', pData[0].SRC);

                                                }

                                        }

                                )



Let save and run the page. That's it. Happy coding!!