Aug 17

In the last blog post I talked about the idea of using region plugins for defining query sources rather than acting as a standalone plugin, and the post before that: transforming apex button references into different Ext form items. This post is focused on bringing those two approaches together. i.e. in our development environment we used a stripped down region plugin to define a query source which is used to supply the list of radio items in an Ext Button Menu within the parent region/report.

Perhaps the following two images will explain what I’m failing to do with words…

In the above two images; the first shows the display of two separate menu’s with different items (it’s been photoshopped to show you two tabs of the tabpanel as the menu’s are on separate tabs). The second shows the APEX IDE and the menu plugins which are used to define the query source for the menu items.

The difference in approach to the “A button is not always a button” post is that instead of building a json object in the page header with our shortcuts and using a function to clean some malformed JSON outputted by our templates. We changed the design to generate the entire region toolbar JSON object in the page header, as it allowed a more cleaner and maintainable approach and opened up the ability to query the APEX data dictionary and process sub regions as we looped through each parent region at a time.

The following code example from our initial prototype (which only works for one menu button per region) should give you an idea of how we query the APEX data dictionary to build the toolbar object


--
-- Lets loop through all our page regions to create our region toolbar for each
--
FOR c IN
( SELECT *
  FROM   apex_application_page_regions
  WHERE  application_id = v_app_id
  AND    page_id        = v_page_id
  AND    source_type    NOT IN ('EXT_BUTTON_MENU') -- ignore our stripped pseudo plugins
  AND    extjs_utils.auth_condition_check(condition_type,condition_expression1,condition_expression2,authorization_scheme) = 0
)  LOOP
  v_toolbarObj := JSON_LIST();
  --
  -- Lets loop through all our page buttons to create our region toolbar
  --
  FOR c1 IN
  ( SELECT pb.region_id
    ,      label
    ,      nvl(redirect_url,'apex.submit('''||button_name||''');') link
    ,      button_attributes
    ,      template
    FROM   apex_application_page_buttons pb
    ,      apex_application_temp_button  tmp
    ,      apex_applications             app
    WHERE  pb.application_id  = v_app_id
    AND    pb.page_id         = v_page_id
    AND    pb.region_id       = c.region_id
    AND    tmp.application_id = pb.application_id
    AND    app.application_id = pb.application_id
    AND    tmp.template_name  = pb.button_template
    AND    tmp.theme_number   = app.theme_number
    AND    extjs_utils.auth_condition_check(pb.condition_type,pb.condition_expression1,pb.condition_expression2,pb.authorization_scheme) = 0
    ORDER by pb.button_sequence
  ) LOOP
    --
    -- Lets check our button attributes for shortcuts
    --
    v_shortcut_name := regexp_replace(c1.button_attributes, '.*"(EXT_\w+)".*','\1');
    v_shortcut_name := CASE v_shortcut_name
                         WHEN c1.button_attributes THEN NULL
                         ELSE v_shortcut_name
                       END;
    IF v_shortcut_name IS NOT NULL THEN
 
      FOR c2 IN
      ( SELECT shortcut_name
        ,      shortcut
        FROM   apex_application_shortcuts
        WHERE  application_id = v_app_id
        AND    shortcut_name  = v_shortcut_name
      )  LOOP
        v_shortcut := c2.shortcut;
        --
        -- Lets loop through our shortcut and replace our menu references with a JSON object
        --
        WHILE instr(v_shortcut,'#MENU:') > 0 LOOP
          FOR c3 IN
          ( SELECT source_type
            ,      region_source menu_sql
            FROM   apex_application_page_regions
            WHERE  application_id   = v_app_id
            AND    page_id          = v_page_id
            AND    parent_region_id = c.region_id
            AND    source_type      = 'EXT_BUTTON_MENU'
          ) LOOP
            --
            -- Lets execute our query and return the result encoded in a JSON object
            --
            v_json := sql_to_json( p_sql => c3.menu_sql );
            v_shortcut := regexp_replace(v_shortcut,'(\$MENU:\w+\$)',v_json,1,1)..........

In the above we query all the regions on the page and ignore any of our pseudo plugin regions. We then build up the toolbar JSON object with the assistance of PLJSON and then loop through each of the buttons defined for the region and use the defined button template and make the necessary string replacements e.g. #BUTTON_ATTRIBUTES#. But before we do, we check the button attributes to see if a custom MENU shortcut has been defined and if so we extract the shortcut name and query the shortcut source. We then extract any MENU definition in the shortcut source and then in the c3 cursor loop we query “apex_application_page_regions” and check the source type matches our plugin name and we use this SQL definition and execute it to get the results for the named menu.

So what it allows us to do from a development point of view is define a single button template e.g. radio menu, and use our pseudo plugins SQL to define the menu items. Essentially our toolbar menu button is made up of a button template, shortcut, and plugin region. All three components can be subscribed and published across all applications in the workspace so we get the benfit of code centralization and any additional custom config for the button menu can be defined by either using multiple shortcuts or some additional config in #BUTTON_ATTRIBUTES#.

In order to make sure the plugin region never displays, we use a template named either “Ext.Exclude” which wraps the content in a DIV with style=”display:none;”. Optionally we can use another template named “Ext.Destroy” which uses the Ext.onReady function and removes the region/DIV from the DOM on page load. Both come in very handy in different situations. We simply ignore regions which have these templates assigned to them within our viewport generation code.

Note: you will see this error in the region source when you use a stripped plugin like we have

ORA-20100: No render function has been defined for plug-in PLUGIN_EXT_BUTTON_MENU

 

however this is never visible because the template we define either destroys the region or hides it from display.

Tagged with:
Jul 21

I’ve started doing some R&D with region plugins, one of the things I like is that we can define the “Region Source” as a SQL statement and set the minimum and maximum columns allowed. This means that we get builtin SQL statement parsing to make sure our queries are syntactically correct when we define our plugin query source, which is really nice. We can even show query examples so we the developer know what query structure is required when defining them.

Now on initial investigation one might think that you can have only one query associated with a plugin, and by definition that’s true, but have you considered creating a plugin that’s actually made up of say 5 plugin definitions? i.e. we have one parent plugin and 4 child plugins which work together to produce 1 result. Why would we want to do this? Consider a menu bar, we may want each menu e.g. “File”, “Edit”, “View” etc. to be defined from separate SQL queries. Since we only have one query definition that we can define per plugin, why don’t we just create one master plugin with X many child plugins. The child plugins will be stripped down, i.e. all they do is just define our query sources and with the option of setting a template to define what sort of component it is. We then use the APEX data dictionary within our parent plugin to locate the direct children during the rendering phase, execute them and use the results.

This approach can give us greater flexibility and visibility of our plugin definition as it’s visible and editable through the APEX IDE with a visual tree structure, thus ensuring we have less code and object maintenance on the backend. Potential other uses for a plugin with multiple query definitions could be grids within grids within grids. Anyway it’s early days for me I’m just tinkering around seeing what the possibilities could be. As I stated in an earlier post my favourite feature is the new parent/child setting for regions, it’s opened Pandora’s box in my eyes ;)

Tagged with:
Jul 16

We’ve bitten the bullet and updated our internal development environments to APEX 4.0 which includes our APEX/Ext development framework. We had no troubles during installation. Post Installation, there have only been a few minor issues which we’ve run into which are:

  1. Changing our javascript override for “doSubmit” to “apex.submit”, we use this for upload/downloading multiple clobs and other things….
  2. Catering for data dictionary changes for item type “Display As” definitions
  3. Viewing session state: collection information does not appear to work
  4. We’ve had to move the developer toolbar on page load using javascript (i.e in runtime development mode) as it sometimes overlays important navigation on the page e.g. bottom tabs on a tabpanel etc.
  5. That’s it!!

APEX 4.0 is a big jump for the product and personally I must say that the development team has done a fantastic job as we were quite worried about the impact this version would have on all the previous custom development we’d performed against earlier versions. We can breathe easy now ;)  

What’s my favourite part/new feature? Plugins come a close second but my favourite new feature is the ability to create a region within a region. Now you’re probably thinking that I’ve got a couple of screws loose! but for me this single feature has just opened the door for a perfect design for APEX and Ext integration, as we can now build/define page components/templates in the exact same form Ext creates them, e.g. Viewport -> Layout -> Panel -> Form e.g.

 

Note: the above is just a quick mockup as all regions are defined as “HTML”, normally the region types would reflect their specific type e.g. a Tree would be a Tree, a Form would be a Form etc.

I am a little biased though on the features that I like because I’m purely focused on APEX and Ext, but I’m also spicing things up by using a sprinkling of jQuery here and there, so in the future we’ll be documenting the sociability of APEX/Ext/jQuery, as we’d like to still use some of the productivity gains we get from dynamic actions and the likes.

Finally we’re curious if anyone would purchase a license and support for a commercial plugin, we’re considering building an APEX 4.0 plugin for the Ext Gantt demo with full editing support. Just leave a comment to start a discussion on the (controversial) topic…

Tagged with:
preload preload preload