APEX Email Templates - Advanced Formatting

APEX Email Templates - Advanced Formatting

·

6 min read

Introduction

I have been using APEX Email Templates since their release in APEX 18.1 (I think). They offer a clean way to separate the content of your email from the layout. In this post, I will review two advanced features of APEX Email Templates, which allow you to get even more from this excellent feature.

  • Template Directives - You can use Template Directives in APEX Mail Templates. They offer an excellent method of deciding what will be displayed from the UI instead of in the data source.

  • In-Line CSS Styling - Adding CSS to your template lets you style your email content to emphasize important information and give your emails a more professional look.

Email Templates Primer

With APEX Email templates, you provide a JSON document to the APEX_MAIL API via a parameter called p_placeholders. APEX then takes the values in the JSON and replaces the placeholders in the template (identified by placeholders like #PO_NUMBER#) with the associated values in the JSON.

Example APEX_MAIL API Call

begin
  apex_mail.send 
   (p_to                 => 'jon@cloudnueva.com',
    p_template_static_id => 'PO_APPROVALS',
    p_application_id     => 1020,
    p_placeholders       => '{' ||
    '    "PO_NUMBER":'     || apex_json.stringify( '1000' ) ||
    '   ,"PO_STATUS":'     || apex_json.stringify( 'PENDING' ) ||
    '   ,"SUBJECT":'       || apex_json.stringify( 'Approval Required' ) ||
    '   ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
    '   ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
    '   ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
    '   ,"PO_AMOUNT":'     || apex_json.stringify( '$12,000.00' ) ||
    '   ,"BUYER_NAME":'    || apex_json.stringify( 'Bob the Builder' ) ||
    '}' );
  apex_mail.push_queue;
end;

Example Template

The email template contains the placeholder tags, e.g. #APPROVER_NAME#

Screenshot of HTML code for an email template. The code includes placeholders for approver name, purchase order number, subject, supplier name, and purchase order amount.

Result

The result is a formatted email, which looks just OK.

Email notification for PO 1000 approval required. The email is from jon@cloudnueva.com to Jonathan Dixon. The subject is "APEX PO Approvals." The body of the email states that Purchase Order 1000 requires approval and includes details: Supplier - ABC Materials INC, Amount - $12,000.00, Buyer - Bob the Builder.

💪
With a little extra work, we can do better!

Template Directives

Template Directives allow you to add conditional logic to Email Templates to conditionally display content in the resulting email.

Benefits

By injecting logic into the Template, Template Directives allow you to:

  • Reduce the number of Email Templates you need to create (and maintain).

  • Remove conditional logic from the code that generates the placeholders. You often only need one procedure instead of many to generate the placeholder JSON.

Example 'if' Directive

Let's improve the PO Approval Email template by adding bold red text to the email Header if the PO is over $12,000.

Oracle APEX Email Template - if Template Directive

{if HIGH_VALUE_PO/}
  <br><span class="po-high-value">#HIGH_VALUE_PO#</span>
{endif/}

The if condition checks if the placeholder #HIGH_VALUE_PO# has a value. If it has a value, it is displayed in the email. If it does not, no content is output to the email header.

Example case Directive

Next, let's display additional text in the email header indicating if the email is requesting approval or is being sent to confirm the PO has been Approved (or Rejected).

Oracle APEX Email Template - case Template Directive

{case PO_STATUS/}
  {when APPROVED/}
    <br><span class="po-approved">PO Approved</span>
  {when REJECTED/}
    <br><span class="po-rejected">PO Rejected</span>
  {otherwise/}
    <br><span class="po-pending">PO Pending Approval</span>
{endcase/}

This directive checks the value of the placeholder #PO_STATUS# and emits different text depending on the PO Status. I will discuss the CSS classes in the next section.

In-Line Custom CSS

Now that we have made the template more dynamic, let's turn our attention to improving the look of the email. We can easily do this by adding some CSS.

🤔
The ability to add our own CSS to an email template was not immediately obvious to me.

You may have noticed some CSS classes in the Email Header Template Directives above, e.g., po-high-value, po-approved. We can add our custom CSS to the Advanced section of the email template.

Oracle APEX Email Template - Advanced Section

In a new template, the Advanced section is empty. However, if we click the 'Load Default HTML' button, we can populate it with the default HTML, giving us a starting point. We can then add our CSS in the <style> section of the 'HTML Template' property.

Oracle APEX Email Template - Advanced Section with Custom CSS

I added the CSS (within the <style> tags) to get the final email result described later in the post.

.subject {
  font-size:2.0em;
  font-weight: bold;
}
.po-high-value {
  font-size:1.5em;
  color: red;
  font-weight: bold;
}
.po-approved {
  font-size:1.25em;
  color: green;
  font-weight: bold;
}
.po-rejected {
  font-size:1.5em;
  color: red;
  font-weight: bold;
}
.po-pending {
  font-size:1.5em;
  color: blue;
  font-weight: bold;
}
.my-table td,
.my-table th {
    padding: 5px;
    border: 1px solid #000;
}
.my-table,
.my-table td,
.my-table th {
    border: 1px solid #000;
}
.my-table {
    width: 100%;
    border-collapse: collapse;
    font-size: smaller;
}
.my-table th {
    background-color: #d3d3d3;
    text-align: left;
    width: 33%;
}

Formatting the PO Details HTML Table

You may notice some additional classes related to my-table. These classes will style the table to show purchase order details. Here is a screenshot of the Body Section of the Email Template, where you can see the <table> definition.

The Final Result

Let's look at three scenarios showing the different phases of PO Approval.

💡
These scenarios illustrate that with Template Directives and some simple CSS, we can utilize one email template and one JSON document to produce three very different emails.

High-Value PO Pending Approval

begin
  apex_mail.send 
   (p_to                 => 'jon@cloudnueva.com',
    p_template_static_id => 'PO_APPROVALS',
    p_application_id     => 1020,
    p_placeholders       => '{' ||
    '    "PO_NUMBER":'     || apex_json.stringify( '1001' ) ||
    '   ,"PO_STATUS":'     || apex_json.stringify( 'PENDING' ) ||
    '   ,"SUBJECT":'       || apex_json.stringify( 'Requires Approval' ) ||
    '   ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
    '   ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
    '   ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
    '   ,"PO_AMOUNT":'     || apex_json.stringify( '$12,000.00' ) ||
    '   ,"BUYER_NAME":'    || apex_json.stringify( 'Bob the Builder' ) ||
    '}' );
  apex_mail.push_queue;
end;

APEX Email Result - High-Value PO

Regular PO Approved

begin
  apex_mail.send 
   (p_to                 => 'jon@cloudnueva.com',
    p_template_static_id => 'PO_APPROVALS',
    p_application_id     => 1020,
    p_placeholders       => '{' ||
    '    "PO_NUMBER":'     || apex_json.stringify( '1001' ) ||
    '   ,"PO_STATUS":'     || apex_json.stringify( 'APPROVED' ) ||
    '   ,"SUBJECT":'       || apex_json.stringify( 'Approved' ) ||
--    '   ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
    '   ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
    '   ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
    '   ,"PO_AMOUNT":'     || apex_json.stringify( '$9,000.00' ) ||
    '   ,"BUYER_NAME":'    || apex_json.stringify( 'Bob the Builder' ) ||
    '}' );
  apex_mail.push_queue;
end;

APEX Email Result - PO Approved

PO Rejected

begin
  apex_mail.send 
   (p_to                 => 'jon@cloudnueva.com',
    p_template_static_id => 'PO_APPROVALS',
    p_application_id     => 1020,
    p_placeholders       => '{' ||
    '    "PO_NUMBER":'     || apex_json.stringify( '1001' ) ||
    '   ,"PO_STATUS":'     || apex_json.stringify( 'REJECTED' ) ||
    '   ,"SUBJECT":'       || apex_json.stringify( 'Rejected' ) ||
--    '   ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
    '   ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
    '   ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
    '   ,"PO_AMOUNT":'     || apex_json.stringify( '$9,000.00' ) ||
    '   ,"BUYER_NAME":'    || apex_json.stringify( 'Bob the Builder' ) ||
    '}' );
  apex_mail.push_queue;
end;

APEX Email Result - PO Rejected

Conclusion

In this post, I explored the advanced features of APEX Email Templates, focusing on Template Directives and In-Line CSS Styling. Template Directives allow conditional content to be displayed within emails, reducing the need for multiple templates and simplifying placeholder JSON generation. In-line CSS Styling enhances the visual appeal of emails.

Finally, I demonstrated how these techniques can produce different email outputs for various Purchase Order (PO) statuses.

Â