Create a dynamic membership card on APEX

Search for a command to run...

No comments yet. Be the first to comment.
Oracle APEX already includes Font APEX as the default icon library for Universal Theme. In most cases, that is enough. But in one of my APEX apps, I needed a few icons that were not available there, s

Looking to give your Oracle APEX mobile app a modern, native feel? Here’s a quick hack: add a floating action button that stays anchored at the bottom corner just like in popular mobile apps. This sma

APEX 26.1 has been updated to the Universal Theme. While much of the attention in this release is on AI features, I think the UT improvements are just as important for developers like me who care abou

The apex_barcode package offers a PL/SQL API to generate various types of barcodes. You can output barcodes as SVG (Scalable Vector Graphics) values or as PNG file blobs, making it easy to embed them

Oracle APEX makes it easy to get data on screen fast, but often, the default tabular output isn’t enough. What if you want to highlight statuses, add icons, or display badges all without writing compl

In this post, I will demonstrate how to dynamically embed data into images and download them. For this demo, I will be creating a membership card by adding the membership details to a pre-defined template.
First, let's add the membership template image to the static application files. I will use a file I created using canva.com

Open your APEX application and go to Shared Components.
Click on Static Application Files.
Click the Create button and upload the image file.
We are going to need later the file reference. (e.g. #APP_FILES#membership_canvas.png)
To store the data, I created a table named "membership_card", which includes the following details:
create sequence membership_card_seq;
create table membership_card (
id number default on null membership_card_seq.NEXTVAL
constraint membership_card_id_pk primary key,
name varchar2(255),
membership_number number,
image blob
)
;
We are now able to create an APEX page that generates the card. The page will include a select list item (P2_NAME) that allows us to choose the data from the membership by using the following query as the source.
select name,
id
from membership_card
order by 1
To display the image, we require a standard region where we can add the following code to load the image that was previously added to the shared components. But we don't need to show it, so we will add style="display:none".
<img id="img_membership_card" style="display:none" src="#APP_FILES#membership_canvas.png" crossorigin="anonymous"/>
<canvas id="canvas" />
The next step is to create an AJAX callback process for retrieving the membership data.
DECLARE
ln_error_code NUMBER;
lv_error_msg VARCHAR2(4000);
BEGIN
FOR i IN 1..apex_application.g_f01.count
LOOP
FOR x IN
(
SELECT mb.name,
to_char(mb.expiration_date,'fmDay, fmDD fmMonth, YYYY') as expiration_date ,
substr(membership_number,1,4)||' '||substr(membership_number,5,4)||' '||substr(membership_number,9,4)||' '||substr(membership_number,13,4) as membership_number,
apex_web_service.blob2clobbase64(p_blob => mb.image_file) as img
FROM membership_card mb
WHERE mb.id = apex_application.g_f01(i))
LOOP
apex_json.open_object;
apex_json.Open_array('output');
apex_json.open_object;
apex_json.WRITE('membershipNumber',x.membership_number);
apex_json.WRITE('expirationDate',x.expiration_date);
apex_json.WRITE('name',x.name);
apex_json.WRITE('image',x.img);
apex_json.close_object;
apex_json.close_array;
apex_json.close_object;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
apex_json.open_object;
apex_json.Open_array('output');
apex_json.open_object;
apex_json.WRITE('lv_error_code', 0);
apex_json.WRITE('lv_error_msg', SQLERRM);
apex_json.close_object;
apex_json.close_array;
apex_json.close_object;
END;
Note that we are utilizing the apex_web_service.blob2clobbase64 function to convert the member picture blob into clob base64 format, which enables us to easily use it within the JavaScript code.
Now let's create the JavaScript code that will retrieve the data, embed it into the template image, and generate a new image.
function generateCard(id) {
/* get the template image size and create a canvas */
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = $("#img_membership_card").width();
canvas.crossOrigin = "Anonymous";
canvas.height = $("#img_membership_card").height();
/* load the membership data calling the AJAX process */
apex.server.process(
"LOAD_DATA",
{
f01: id,
pageItems: "#P2_NAME"
},
{
success: function (pData) {
let membershipNumber,
name,
expirationDate,
image,
img = new Image();
img.onload = function () {
ctx.drawImage(this, 450, 20, 102, 100);
};
/* get the membership data returned by the AJAX callback process */
image = pData.output[0].image;
membershipNumber = pData.output[0].membershipNumber;
name = pData.output[0].name;
expirationDate = pData.output[0].expirationDate;
/* print the data onto the canvas */
img.src = "data:image/png;base64," + image;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage($("#img_membership_card").get(0), 0, 0);
ctx.font = "18pt monospace";
ctx.fillStyle = "#ffffff";
ctx.fillText(membershipNumber, 40, 200);
ctx.font = "12pt Arial";
ctx.fillStyle = "#000000";
ctx.fillText(name, 120, 245);
ctx.fillText(expirationDate, 120, 280);
},
}
);
}
/* function to download the image */
function downloadCard() {
var link = document.createElement("a");
link.download = "membership_card.jpg";
link.href = document.getElementById("canvas").toDataURL();
link.click();
}
Now, we simply need to create a dynamic action fired by the select list to invoke the JavaScript mentioned above.
Right-click on the P2_NAME item and select Create Dynamic Action. That should look as follows
Name: Print Membership Card
Event: Change
Selection Type: Item
Item(s): P2_NAME
Create an Execute Javascript Code action and add the code below
generateCard(apex.item("P2_NAME").getValue());
We can now run the page. When we select a value from the select list, the template image is populated with the membership data generating a new image.

To download the membership card, we can create a button with the action "Redirect to URL" and add the following code as the target.
javascript:downloadCard();