Sunday, May 31, 2026

Oracle APEX- Implement Drag & Drop Tree Structure

Oracle APEX tree region or page is not provided the drag and drop features by default. When you think to implement such kind of features, you need to think from out of the box. To add this features you need to build your tree structure from scratch. Using javascript library named "jstree", I have implemented "drag & Drag" features in my custom tree structure. Let me show the whole process step by step. You can find a visual assistance from here.


STEP 1: Create a blank page and named it "Drag & Drop Tree".

STEP 2: Select page and open JavaScript "File URLs" code editor. Copy the link from "cdnjs.com/libraries/jstree" and paste the below link here- https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.17/jstree.min.js (Step 2 or 3 any one is required).

STEP 3: (Optional) Copy the code from the above URL for offline support. Open nodepad and paste here. Save the file as jstree.js file. Go to APEX page and click on "Shared Component" icon. Click on "Static Application Files" and upload the jstree.js file. Copy the "Reference" link. Go back to APEX page and open JavaScript "File URLs" code editor. Paste the "Reference" link here.

STEP 4: Create a new region and set the below properties-

HTML Code : <div id='emp-tree'></div>

STEP 5: Create a button under the above region and set the properties like below-

Name: BTN_EXPAND_ALL

Label: Expand All

Region: Emp Tree

Slot: Edit

Button Template: Icon

Hot: Yes (Switch on)

Template Options:

Size: Small

Icon: fa-expand

STEP 6: Create another button and set the properties like below-

Name: BTN_COLLAPSE_ALL

Label: Collapse All

Region: Emp Tree

Slot: Edit

Button Template: Icon

Hot: Yes (Switch on)

Template Options:

Size: Small

Type: Danger

Spacing Left: Small

Icon: fa-compress

STEP 7: Click on the process icon from the navigation pane. Right click on "Ajax Callback" and Select "Create Process". Set it properties like-

Name: GET_DATA

PL/SQL Code: apex_json.open_array;

FOR i IN (

SELECT employee_id AS emp_id 

, NVL(manager_id,0) AS parent_id

, first_name||' '||last_name AS emp_name

FROM employees1

ORDER BY employee_id

) LOOP

apex_json.open_object;

apex_json.write('EMP_ID', i.emp_id);

apex_json.write('PARENT', i.parent_id);

apex_json.write('NAME', i.emp_name);

apex_json.close_object;

END LOOP;

apex_json.close_all;

STEP 8: Click on the "Navigator" icon and select page. Open the "Execute when Page Loads" code editor and paste the below code-

function buildTree(items) {

const map = {};

const root = [];


//Assign temporary unique key for tree

items.forEach((item, index) => {

map[index] = {...item, children:[], _uniqueId: index}

});


//Build Hierarchy

items.forEach((item, index) => {

if(item.PARENT === 0) {

root.push(map[index]);

} else {

//Find matching parent by EMPLOYEE ID

const parent = items.find(p=> p.EMP_ID === item.PARENT);

if(parent) {

const parentIndex = items.indexOf(parent);

map[parentIndex].children.push(map[index]);

}

}

});

return root;

}

//Convert to tree node recursively

function convert2tree(node) {

return {

text: node.NAME,

id: 'node_'+node.EMP_ID,

emp_id: node.emp_id,

parent_id: node.PARENT,

children: node.children.map(convert2tree)

}

}


apex.server.process(

'GET_DATA'

, {}

, {

dataType: 'json',

success: function(pData) {

try {

const treeData = buildTree(pData);


$('#emp-tree').jstree({

core: {

data: treeData.map(convert2tree),

check_callback: true

},

plugins:['dnd']

})

} catch (err) {

console.log('Tree build error = '+err);

}

},

error: function(err) {

console.log('AJAX error = '+ err);

}

}

)


$('#emp-tree').on('move_node.jstree', function(e, data) {

const nodeEl = $('#'+ data.node.id +'_anchor');

nodeEl.addClass('drag-highlight');

})

STEP 9: Select the "BTN_EXPAND_ALL" button and create a dynamic action here. Set it properties like-

Name: Expand Tree

Event: Click

Button: BTN_EXPAND_ALL

STEP 10: Select the newly create true action and set it propertieslike below-

Action: "Execute JavaScript Code"

Code: $('#emp-tree').jstree('open_all');

STEP 11: Select the "BTN_COLLAPSE_ALL_ALL" button and create a dynamic action here. Set it properties like-

Name: Collapse Tree

Event: Click

Button: BTN_COLLAPSE_ALL

STEP 12: Select the newly create true action and set it propertieslike below-

Action: "Execute JavaScript Code"

Code: $('#emp-tree').jstree('close_all');

STEP 13: Select page and open CSS > File URLs Code editor. Paste the link here- https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.17/themes/default/style.min.js (Step 13 or 14 any one is required).

STEP 14: Open another new tab and paste the link into the url- cdnjs.com/libraries/jstree. Copy the link (https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.17/themes/default/style.min.js) from here and paste it to the url. Copy the css code from here and open a blank nodepad and paste the css code here. Save it as style.css. Go to the APEX page and click on the "Shared Components" icon. Select "Static Application Files" and upload the style.css file. Copy the "Reference" link. Return to the page and open CSS > File URLs code editor. Paste the "Reference" link here.


That's it for today. Next episode, I'll show the rest of that series (Implement DML operation). 

No comments:

Post a Comment