Skip to content

Walkthrough: Simple Region Plugin

Jeffrey Kemp edited this page Nov 1, 2019 · 5 revisions

Walkthrough #1: Create a "hello world" APEX Plugin

This tutorial/walkthrough will guide you to create your first APEX plugin. Having completed this tutorial you will be familiar with the process of creating a plugin from scratch and customising it. The walkthrough assumes you are already familiar with using APEX to build applications. The steps were tested in APEX 19.1 but they should work much the same in other releases.

Pre-requisites

  • access to an APEX workspace
  • a sample table with some data, e.g. "EMP"

Tip: when you get to a step that says "Test", make sure to test your work so far. If anything doesn't work, don't try to push on to the next step - take the time to understand what's gone wrong and correct it. What you learn in the process will be invaluable.

Basic plugin screenshot

Instructions

  1. Login to your workspace in APEX.

  2. In the Application Builder, Create a New Application. It just needs a name, nothing fancy.

  3. On page 1, add a region to the Content Body of type PL/SQL Dynamic Content.

  4. Set the code for the region to:

    for r in (select ename from emp order by dbms_random.value) loop
        htp.p(r.ename || ' ');
    end loop;
    
  5. Save and run the page to test it.

  6. Go to https://github.com/Dani3lSun/apex-plugin-templates

  7. Download the zip or clone it in your git client

  8. In APEX, go to Shared Components, Plugins

  9. Import region_type_plugin_region_template.sql

  10. Name = "List All The Things"

  11. Internal Name = "SAMPLE.LIST_ALL_THE_THINGS"

  12. Apply Changes

  13. On Page 1, drag and drop the plugin region onto the page

  14. Title = "List All The Things"

  15. Test. Examine the HTML generated in the region.

  16. Comment-out the apex_css.add_file code

  17. Modify render_region at this point:

    -- write region html
    sys.htp.p('<div id="' || l_region_id ||
              '" class="my_region_class" attr1="' || l_attr_01 ||
              '" attr2="' || l_attr_02 || '">');
    for r in (select ename from emp order by dbms_random.random) loop
      sys.htp.p(r.ename || ' ');
    end loop;
    sys.htp.p('</div>');
    
  18. Test.

  19. In render_region, replace the add_onload_code portion:

    apex_javascript.add_onload_code(p_code => 'listAllTheThings.init(' ||
        '"' || p_region.static_id || '",' || '{' ||
        '"ajaxIdentifier":"' || apex_plugin.get_ajax_identifier || '",' ||
        '"ajaxItems":"' || apex_plugin_util.page_item_names_to_jquery(
                              p_region.ajax_items_to_submit) || '",' ||
        '"attr1":"' || l_attr_01 || '",' ||
        '"attr2":"' || l_attr_02 || '"' ||
    '});');
    
  20. Add this to ajax_region:

      l_buffer varchar2(32767);
    BEGIN
      apex_debug.message('ajax_region');
    
      for r in (select ename from emp order by dbms_random.random) loop
        l_buffer := l_buffer || ' ' || r.ename;
      end loop;
      l_buffer := ltrim(l_buffer);
    
      sys.owa_util.mime_header('text/plain', false);
      sys.htp.p('Cache-Control: no-cache');
      sys.htp.p('Pragma: no-cache');
      sys.owa_util.http_header_close;
    
      sys.htp.p('{"names":"' || l_buffer || '"}');
    
  21. Create a file listAllTheThings.js with the following contents, and upload it to the plugin:

    var listAllTheThings = {
    
        init: function (regionId, a) {
            apex.debug("listAllTheThings.init", a.attr1, a.attr2);
            apex.jQuery("#"+regionId).bind("apexrefresh",function(){
                listAllTheThings.refresh(regionId, a);
            });
        },
        
        refresh: function (regionId, a) {
            apex.debug("listAllTheThings.refresh", a.attr1, a.attr2);
            apex.server.plugin
              (a.ajaxIdentifier
              ,{ pageItems: a.ajaxItems }
              ,{ dataType: "json"
                ,success: function( pData ) {
                  apex.debug("success names="+pData.names);
                  $("#"+regionId+"_myregion").html(pData.names);
                  apex.jQuery("#"+regionId).trigger("apexafterrefresh");
                }
              } );
        }
    };
    
  22. In render_region, modify the javascript add_library call:

    -- add JavaScript files
    apex_javascript.add_library(p_name           => 'listAllTheThings',
                                p_directory      => p_plugin.file_prefix,
                                p_version        => NULL,
                                p_skip_extension => FALSE);
    
  23. On page 1, add a REFRESH button to the region

  24. Dynamic action on button click to Refresh the plugin region

  25. Test. Using Network inspector, after clicking the Refresh button examine the ajax call, and its response.

  26. Change the add_onload_code bit to this:

    apex_javascript.add_onload_code(p_code => 'listAllTheThings.init(' ||
        apex_javascript.add_value(p_region.static_id) || '{' ||
        apex_javascript.add_attribute('ajaxIdentifier',
                                      apex_plugin.get_ajax_identifier) ||
        apex_javascript.add_attribute('ajaxItems',
                                      apex_plugin_util.page_item_names_to_jquery(
                                          p_region.ajax_items_to_submit)) ||
        apex_javascript.add_attribute('attr1', l_attr_01) ||
        apex_javascript.add_attribute('attr2', l_attr_02,
                                      false,false) ||
    '});');
    

    (add_value and add_attribute make the values safe for embedding in javascript, but they do not protect against cross-site scripting so in some cases you may need to call sys.htf.escape_sc as well)

  27. Remove the javascript add_library call, and set File URLs To Load - Javascript to:

    #PLUGIN_FILES#listAllTheThings.js
    
  28. On page 1, set the plugin attributes (attr1 and attr2).

  29. Test. It should look more or less like the image at the top of this page. Examine the HTML generated. Examine the call to listAllTheThings.init.

You can’t perform that action at this time.