Search This Blog

Thursday, July 10, 2025

How do I Wire the Delete button to DELETE and Refresh the Report

 In Oracle APEX, adding a Delete button to a Classic Report is only the first step; wiring it correctly to perform the deletion and refresh the report dynamically is essential for a seamless user experience. This process involves creating the backend logic to delete the selected record and ensuring the report refreshes immediately to reflect the changes without requiring manual page reloads. Properly wiring the Delete button improves application responsiveness and maintains data integrity by providing instant feedback to the user.

In Oracle APEX, wiring a Delete button to perform a DELETE operation and then refresh the Classic Report involves several detailed steps. This ensures that when a user clicks the Delete button, the corresponding record is removed from the database, and the report updates immediately to reflect this change.

Step 1: Add a Delete Button in the Classic Report
When designing your Classic Report, include a column that contains a Delete button or link for each row. This can be done by adding a column with HTML markup or by using a link column type with an icon or button style.

Example SQL snippet to add a Delete link:

SELECT EMPLOYEE_ID,
       FIRST_NAME,
       LAST_NAME,
       '<button class="delete-btn" data-id="' || EMPLOYEE_ID || '">Delete</button>' AS DELETE_BUTTON
FROM EMPLOYEES

Here, each button has a data-id attribute storing the unique identifier of the record.

Step 2: Create a Dynamic Action to Handle the Delete Button Click
In your APEX page, create a Dynamic Action triggered by a click on the Delete button. Configure it as follows:

  • Event: Click

  • Selection Type: jQuery Selector

  • jQuery Selector: .delete-btn (matches the CSS class used on the buttons)

Step 3: Add a True Action to Execute the DELETE Statement
Add a True Action of type “Execute PL/SQL Code” that performs the DELETE operation on the database. The PL/SQL block will use the value of the record’s ID passed from the button click.

Example PL/SQL block:

BEGIN
  DELETE FROM EMPLOYEES WHERE EMPLOYEE_ID = :P1_EMPLOYEE_ID;
  COMMIT;
END;

Here, :P1_EMPLOYEE_ID is a page item that you will set dynamically to the button’s data-id.

Step 4: Set the Page Item Dynamically Using JavaScript
Before the PL/SQL block runs, add a JavaScript action to assign the clicked record’s ID to the page item. Use this code:

var empId = $(this.triggeringElement).data('id');
$s('P1_EMPLOYEE_ID', empId);

This assigns the ID to the hidden page item P1_EMPLOYEE_ID which the PL/SQL block uses.

Step 5: Refresh the Classic Report Region
Add another True Action of type “Refresh” and select the Classic Report region as the target. This will reload the report data after the deletion completes, showing the updated dataset without the deleted record.

Step 6: Test Your Setup
Run the page, click the Delete button next to any row, and verify the record is removed and the report refreshes immediately.

Additional Tips:

  • Use a confirmation dialog to prevent accidental deletions by adding a “Confirm” True Action before running the DELETE.

  • Ensure the page item used to pass the ID is hidden and cleared after each operation.

  • If the report uses pagination or filters, refreshing the region will keep those intact.

By following these steps, you wire the Delete button to effectively remove records and keep the Classic Report up to date dynamically, enhancing user experience and maintaining data consistency.

Example

Wiring the Delete Button to Delete and Refresh a Classic Report in Oracle APEX

In Oracle APEX, allowing users to delete a record directly from a Classic Report enhances user experience by making data management more interactive. However, after deleting a record, it is also important to refresh the report so that the changes are reflected immediately without requiring a full page reload.

This tutorial explains how to wire a delete button to delete a record and refresh the Classic Report using PL/SQL, AJAX, JavaScript, and Dynamic Actions.

Why Wire the Delete Button to Refresh the Report?

  • Prevents users from seeing outdated data after deletion.

  • Avoids unnecessary full page reloads, making the application more responsive.

  • Provides a seamless experience by updating only the affected region.

Step 1: Modify the Classic Report SQL Query

To include a delete button, modify the SQL query to generate a button inside the report.

SELECT 

    empno, 

    ename, 

    job,

    '<button class="delete-button" data-id="' || empno || '">Delete</button>' AS delete_action

FROM emp

Explanation:

  • The delete-button class is added so that JavaScript can target the button.

  • The data-id attribute stores the empno value, which will be used in the delete action.

Step 2: Create a PL/SQL Process to Delete a Record

Create an On-Demand AJAX Process to handle the deletion.

  1. Go to Shared Components > Application Processes.

  2. Click Create and select On-Demand Process (Ajax Callback).

  3. Name the process DELETE_EMP_RECORD.

  4. Use the following PL/SQL code:

BEGIN

    DELETE FROM emp WHERE empno = :P0_EMPNO;

    COMMIT;

END;

This process removes the employee record identified by empno.

Step 3: Add JavaScript to Handle the Delete Action and Refresh the Report

  1. Open Page Designer and navigate to the Classic Report's properties.

  2. In Page Attributes, go to JavaScript > Function and Global Variable Declaration.

  3. Add the following JavaScript:

$(document).ready(function() {

    $(".delete-button").click(function() {

        var empId = $(this).data("id");


        if (confirm("Are you sure you want to delete this record?")) {

            $.ajax({

                url: "wwv_flow.show",

                type: "POST",

                data: {

                    "p_request": "APPLICATION_PROCESS=DELETE_EMP_RECORD",

                    "p_flow_id": $v("pFlowId"), 

                    "p_flow_step_id": $v("pFlowStepId"),  

                    "p_instance": $v("pInstance"),  

                    "P0_EMPNO": empId

                },

                success: function(response) {

                    alert("Record deleted successfully!");

                    apex.region("classic_report_region").refresh();

                },

                error: function() {

                    alert("Error deleting record.");

                }

            });

        }

    });

});


Explanation:

  • The click function captures the empno from the button’s data-id attribute.

  • The confirm() function asks for user confirmation before deleting.

  • The $.ajax() function makes an asynchronous request to delete the record.

  • If successful, the Classic Report region is refreshed using apex.region("classic_report_region").refresh();.

Replace "classic_report_region" with the Static ID of your Classic Report.

Step 4: Set a Static ID for the Classic Report

  1. In Page Designer, select the Classic Report region.

  2. Locate the Advanced section in the property panel.

  3. Set Static ID to classic_report_region (or any preferred name).

This allows JavaScript to reference and refresh the Classic Report after deletion.


Step 5: Using Dynamic Actions Instead of JavaScript (Alternative Approach)

For a no-code approach, use Dynamic Actions instead of JavaScript.

  1. Select the Classic Report region.

  2. Click Create Dynamic Action.

  3. Set Event to Click.

  4. Set Selection Type to jQuery Selector and enter .delete-button.

  5. Add an Action: Execute PL/SQL Code.

  6. Enter the following code:

BEGIN

    DELETE FROM emp WHERE empno = :P0_EMPNO;

    COMMIT;

END;

  1. Set Page Items to Submit to P0_EMPNO.

  2. Add another Action: Refresh Region.

  3. Set Affected Region to Classic Report Region.

This method eliminates the need for JavaScript while still allowing record deletion and report refresh.

Step 6: Adding a Trash Icon Instead of a Button (Optional Enhancement)

For a cleaner interface, replace the button with a Font Awesome trash icon.

Modify the SQL query to:

SELECT 

    empno, 

    ename, 

    job,

    '<i class="fa fa-trash delete-icon" data-id="' || empno || '"></i>' AS delete_action

FROM emp

Apply CSS styles to improve the appearance:

.delete-icon {

    color: red;

    cursor: pointer;

    font-size: 18px;

}


.delete-icon:hover {

    color: darkred;

}

This change replaces the text button with a red trash icon that performs the same delete action.

Step 7: Prevent Accidental Deletion Using APEX Confirmation Dialog

To replace the default confirm() function with APEX’s built-in confirmation dialog, modify the JavaScript:

$(document).ready(function() {

    $(".delete-button").click(function() {

        var empId = $(this).data("id");


        apex.confirm("Are you sure you want to delete this record?", {

            request: "DELETE_" + empId

        });

    });

});


Create a PL/SQL Process (Before Header) with:

DECLARE

    v_empno NUMBER;

BEGIN

    v_empno := TO_NUMBER(SUBSTR(:REQUEST, 8)); 

    DELETE FROM emp WHERE empno = v_empno;

    COMMIT;

END;

Set the Condition to REQUEST LIKE 'DELETE_%'.

This method enhances user experience with a modal confirmation instead of a JavaScript alert.

Best Practices for Wiring the Delete Button and Refreshing the Classic Report

  • Always use confirmation dialogs to prevent accidental deletions.

  • Ensure the PL/SQL process commits changes to make deletions permanent.

  • Use region refresh instead of full page reload to improve performance.

  • Apply CSS styles or icons to improve the delete button’s appearance.

  • Implement role-based authorization to restrict delete functionality to certain users.

Wiring the delete button to delete a record and refresh the Classic Report in APEX ensures a smooth user experience. By combining PL/SQL, JavaScript, AJAX, and Dynamic Actions, users can remove records without leaving the page. Using confirmation dialogs, icons, and CSS styling further enhances usability.

EXAMPLE:

Step 1: In the HTML expression for the delete button make sure that you have the following in your markup:

  • data-task-id=”#ID#” which in this case is the name of the column that holds the ID value

A screenshot of a computer

Description automatically generated

  • Add the CSS class name “cc-delete-btn”. This will be used by the JQuery call to identify the button.

A screenshot of a computer

Description automatically generated



Step 2- In the “Body” level create a new Page Item

A screenshot of a computer

Description automatically generated

Step 3: change the name and make the field “Hidden”

A screenshot of a computer

Description automatically generated


A screenshot of a computer error

Description automatically generated

Step 4: Add a new Dynamic Task and name it “Delete task”

A green rectangular object with white text

Description automatically generated

Make sure that the “Event Scope” is “Dynamic”

A screenshot of a computer

Description automatically generated

In the “When” section

  • Change the “Selection Type” to “JQuery Selector”

  • Enter “.cc-delete-btn” as the class for the JQuery Selector

A screenshot of a computer program

Description automatically generated

Step 5 – In the “True” Delete Task branch change the name to “Confirm delete Action”

Set the Action to “confirm”, this will generate a confirmation message.

A screenshot of a computer

Description automatically generated

Insert some HTML confirmation message like this:

<span> Are you sure you want to delete?</span>

Set your style. In this case we set it to “Danger”

Set your ICON if you want one in the message.

Two buttons are created: a confirmation and a cancel button.

Set the word “Delete” for the “Confirm Label”.

Set the word “Cancel” in the “Cancel Label”.

A screenshot of a computer program

Description automatically generated

Step 6:  Set the ID for deletion.

Create a new TRUE branch in the dynamic Action

A screen shot of a computer

Description automatically generated

Set the identification’s action to “Execute JavaScript Code

A screen shot of a computer

Description automatically generated

Set the settings to the following:

A computer screen with white text

Description automatically generated


let taskIdToDelete = $(this.triggeringElement).data('taskId');

console.log(taskIdToDelete);

apex.items.P10_TASK_TO_DELETE.setValue(taskIdToDelete);

Code explanation

Declares taskIdToDelete and assigns the data value of the triggered object “taskId” which is somehow associated with the “data-task-id” entry in the code for the button. It saves the ID table column value into the taskIdToDelete variable.

A screen shot of a computer

Description automatically generated

This next piece of code sends the selected value into the console log

 

Since there is no PL/SQL delete code at this point in the process, you can test the button in the page and check the log to see if the ID is getting picked up correctly.

Finally, the following code takes the hidden text item P10_TASK_TO_DELETE  and assigns the taskIdToDelete value

 

Make sure that “Delete task”  is the selected event in “Execution”.

A screenshot of a computer

Description automatically generated 

Step 7 -  Delete the Row from table

Create a “New” Dynamic Action True branch and name it “Delete row from table”

A screenshot of a computer

Description automatically generated

In Identification select the action: “Execute Server-side Code”

A black and white text

Description automatically generated


In settings add the following code:

begin

    delete from table1

    where id = to_number(:P10_TASK_TO_DELETE);

end;


Where :P10_TASK_TO_DELETE is the hidden text field that has the ID column value.

Make sure that you add ALL of the items that you’re passing data with (:P10_TASK_TO_DELETE) as the “Items to Submit” will pass the data from those items to the named items in the sql statement.

A screenshot of a computer program

Description automatically generated

Step 8 – Refreshing the table

Add one more true Dynamic Action branch

A screenshot of a computer

Description automatically generated


Set the identification action to “Refresh”

A screenshot of a computer screen

Description automatically generated

Set the :Selection Type” to “Region” and enter the name of the report in the “Region” area

A screenshot of a computer

Description automatically generated

By correctly wiring the Delete button to execute the deletion process and refresh the Classic Report region, you create a smooth, interactive interface that enhances usability. This approach minimizes user effort, prevents stale data display, and ensures your Oracle APEX application operates efficiently with real-time updates, ultimately delivering a polished and professional user experience.

Tuesday, July 8, 2025

How Do I Troubleshoot SMTP Configuration Issues

 

Introduction
Setting up SMTP configuration in Oracle APEX is essential for enabling your applications to send emails reliably. However, issues can arise from incorrect settings, blocked ports, authentication errors, or provider-specific security policies. Troubleshooting these problems requires a methodical approach—verifying credentials, testing connectivity, and reviewing APEX logs—to identify and resolve the root cause efficiently.

  1. Authentication Errors:

    • Ensure that the SMTP username and password are correct.

    • If using Gmail or Yahoo, create an app-specific password if two-factor authentication is enabled.

  2. Connection Errors:

    • Check if the SMTP server is reachable.

    • Verify the correct port and encryption settings (SSL/TLS).

  3. Emails Not Being Delivered:

    • Ensure the From Address is approved for sending.

    • Check spam filters and email logs.

    • Review APEX_MAIL_QUEUE for pending messages:

SELECT mail_id, sent_date, to_address, status FROM APEX_MAIL_QUEUE;

  1. Gmail/Outlook Blocking the Email:

    • Enable "Less Secure Apps" if necessary (not recommended for production).

    • Ensure the SMTP credentials match the allowed senders in email provider settings.


Each mailbox provider has its own SMTP settings that must be configured correctly to allow Oracle APEX to send emails. By understanding the different configurations required for Gmail, Outlook, Yahoo, and OCI Email Delivery, developers can ensure smooth email transmission in their APEX applications.

Proper SMTP setup ensures that emails are delivered efficiently and securely, reducing the risk of failed or blocked messages.

Troubleshooting SMTP configuration issues in Oracle APEX involves checking several components that work together to enable successful email delivery. If APEX emails are not being sent or received, the cause could lie in incorrect settings, authentication failures, blocked network ports, or missing permissions. Below is a detailed, step-by-step approach to identify and resolve SMTP-related problems.

1. Verify Basic SMTP Settings in APEX
Navigate to Manage Instance > Instance Settings > Email or the corresponding workspace settings.

Check the following fields:

  • SMTP Host Address – Confirm this is the correct mail server address (e.g., smtp.gmail.com, smtp.office365.com, or smtp.email.us-ashburn-1.oci.oraclecloud.com).

  • SMTP Port – Common ports are 587 (TLS), 465 (SSL), or 25 (no encryption). Use the correct one as per your provider’s documentation.

  • Username – Ensure the full email address is entered if required.

  • Password – Confirm it's accurate and up to date. If using app-specific passwords (e.g., Gmail or Yahoo), use that instead of the account password.

  • Security (SSL/TLS) – Match the port you’ve chosen with the correct encryption type.

2. Test Network Connectivity
Ensure that the database server where Oracle APEX is installed can connect to the external SMTP server. From the OS or network layer:

  • Use tools like telnet smtp.server.com 587 or openssl s_client -connect smtp.server.com:465 (depending on your DB OS access).

  • If the server cannot reach the SMTP endpoint, work with your network or firewall team to open the necessary ports.

3. Review Error Logs and Views
Oracle APEX provides two important views for diagnosing mail issues:

  • APEX_MAIL_LOG – Displays results of email send attempts including success or failure messages.

  • APEX_MAIL_QUEUE – Shows pending emails that have not yet been pushed or sent.

Example SQL:

SELECT * FROM APEX_MAIL_LOG ORDER BY SENT_DATE DESC;
SELECT * FROM APEX_MAIL_QUEUE;

Look for error messages like:

  • Connection timed out

  • Authentication failed

  • Sender address rejected

  • Invalid credentials

4. Check Email Address Consistency
Make sure:

  • The p_from address used in APEX_MAIL.SEND matches the one approved by your SMTP provider.

  • Some providers require the sender email to be the same as the authenticated user (especially Gmail, OCI Email Delivery, Office 365).

  • Approved sender domains are set correctly if using OCI Email Delivery.

5. Test Sending an Email
Use the following PL/SQL block to test sending:

BEGIN
  APEX_MAIL.SEND(
    p_to       => 'your@email.com',
    p_from     => 'approved@sender.com',
    p_subj     => 'SMTP Test',
    p_body     => 'This is a test email sent from Oracle APEX.'
  );
  APEX_MAIL.PUSH_QUEUE;
END;

Then check APEX_MAIL_LOG to verify delivery status.

6. Re-check Authentication Requirements
Different SMTP providers have unique authentication rules:

  • Gmail – Requires OAuth or app passwords with 2FA enabled.

  • Office 365 – Requires SMTP AUTH to be enabled and MFA compliance.

  • OCI Email Delivery – Uses generated SMTP credentials and approved sender lists.

If these are not set up properly, authentication will fail even if credentials look correct.

7. Consider Message Content Filters
Some SMTP services reject emails with:

  • Empty subject or body

  • Invalid HTML formatting

  • Suspicious links or keywords

  • Unencoded attachments

Send a minimal test message first before testing formatted content or attachments.

8. Resend Failed Emails (Optional)
If emails failed to send due to a temporary issue (e.g., network failure), they may still be in the mail queue. Re-run:

BEGIN
  APEX_MAIL.PUSH_QUEUE;
END;

This manually pushes queued emails for retry.

9. Work with Your SMTP Provider
If errors persist and logs show rejections or blacklisting, contact your email provider. Share log excerpts to get insight into what’s going wrong (e.g., spam policy violations, throttling, IP restrictions).

Summary of Common Causes and Fixes

  • Wrong port or encryption → Match port 587 with TLS, 465 with SSL

  • Wrong password → Use an app-specific password if required

  • Unapproved sender → Use only verified or approved senders

  • Blocked port → Ensure firewall allows outbound SMTP connections

  • Authentication error → Confirm username/password and policy settings

With methodical checks of settings, network access, and log analysis, SMTP configuration issues in Oracle APEX can be quickly diagnosed and resolved, allowing your applications to send email reliably and securely.

Conclusion
SMTP configuration issues can prevent your APEX applications from delivering important emails, affecting workflows and user communication. By following a structured troubleshooting process—checking network access, verifying SMTP credentials, reviewing logs, and testing with known-good values—you can resolve common problems and restore email functionality. With a stable setup, you’ll ensure dependable email delivery across all your APEX applications.

UI Defaults

 In Oracle APEX, User Interface (UI) Defaults are a set of metadata-driven, table- and column-scoped attributes that APEX consults when it g...