Modern applications are all about better user experience. One powerful UX feature is allowing users to reorder cards using drag & dropβjust like Trello or Jira.
In this blog, Iβll show you how to implement a Draggable Card Region in Oracle APEX and persist the order in the database.
π― What We Are Building
- A Card Region (Card View) based on EMP table
- Users can drag & reorder cards
- Order is saved automatically in database
- Displays a success message after saving
π§± Step 1: Create Card Region Query
Use the following SQL query for your Card Region:
select
EMPNO,
ENAME as CARD_TITLE,
JOB as CARD_SUBTITLE,
'Hired on ' || to_char(HIREDATE, 'DD-MON-YYYY') as CARD_BODY,
case
when DEPTNO = 10 then 'Accounting'
when DEPTNO = 20 then 'Research'
when DEPTNO = 30 then 'Sales'
else 'Operations'
end as CARD_BADGE,
MGR,
SAL,
substr(ENAME, 1, 1) as CARD_INITIALS,
DISPLAY_ORDER
from EMP
order by nvl(DISPLAY_ORDER, 999), ENAMEπ‘ Key Points:
- DISPLAY_ORDER β Used to maintain card position
- order by nvl(DISPLAY_ORDER, 999) β Ensures proper sorting
- CARD_* columns β Required by APEX Card UI
βοΈ Step 2: Include SortableJS Library
Add this in Page β JavaScript β File URLs:
https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.jsπ This library enables drag-and-drop functionality.
π§ Step 3: Enable Drag & Drop (JavaScript)
Add this code in Execute when Page Loads:
var el = document.querySelector('#my_draggable_cards .a-CardView-items');
var sortable = Sortable.create(el, {
animation: 150,
ghostClass: 'u-colors-gray-1',
onEnd: function (evt) {
var orders = [];
document.querySelectorAll('#my_draggable_cards .a-CardView-item').forEach(function(card) {
var id = card.getAttribute('data-id');
if (id) { orders.push(id); }
});
var lWait = apex.util.showSpinner(el);
apex.server.process('SAVE_CARD_ORDER', {
f01: orders
}, {
success: function(pData) {
lWait.remove();
apex.message.showPageSuccess("Card order saved successfully!");
setTimeout(function() {
apex.message.hidePageSuccess();
}, 2000);
},
error: function(request, status, error) {
lWait.remove();
apex.message.showErrors([{
type: "error",
location: "page",
message: "Error saving Card order: " + error,
unsafe: false
}]);
}
});
}
});π Important Configuration
Make sure your Card Region Static ID is:
my_draggable_cardsπ This is required for JavaScript to target the correct region.
π Step 4: Create AJAX Callback Process
Create a Process β AJAX Callback named:
SAVE_CARD_ORDERPL/SQL Code:
begin
for i in 1 .. apex_application.g_f01.count loop
update EMP
set DISPLAY_ORDER = i -- The loop index is the new position
where EMPNO = apex_application.g_f01(i);
end loop;
apex_json.open_object;
apex_json.write('status', 'success');
apex_json.close_object;
exception
when others then
apex_json.open_object;
apex_json.write('status', 'error');
apex_json.close_object;
end;π How It Works
- User drags cards
- JavaScript captures new order (data-id)
- Sends array to APEX (f01)
- PL/SQL updates DISPLAY_ORDER
- Cards reload in saved order
β¨ Final Result
β Drag-and-drop cards
β Instant save without page refresh
β Clean UX with success message
β Fully database-driven ordering
π Benefits
- Improves user experience
- Works with any dataset
- Easy to reuse in multiple apps
- Minimal backend logic
π₯ Pro Tips
- Add Refresh Region after save if needed
- Use Row Locking for multi-user environments
- Add drag handle icon for better UI
- Store order per user (if required)
π― Conclusion
With just a small JavaScript library and an AJAX process, you can transform a static Card Region into a fully interactive, draggable UI component.
π This is a great way to bring modern UX patterns into Oracle APEX applications.
Love coding? Me too! Letβs keep in touch β subscribe to my website for regular chats on Oracle APEX, PL/SQL,SQL JavaScript, and CSS.




