Monday, July 10, 2017

Dynamically Expand a Collapsible Region

I use collapsible regions in APEX all the time. Mostly, to hide away audit information that most users don’t really care about but a few people might want to see. I usually default them to load in the collapsed state so that I can keep a page clutter-free until the user decides they want to take a gander at what lies within. But, what if there is some important information inside the collapsible region? What if the user never expands the region? Don’t worry - its pretty easy to dynamically expand a collapsible region when it has content and collapse it when it doesn’t.

Simply create a collapsible region and go ahead and default it to the collapsed state. For this example, my region contains a classic report. You will also need a hidden page item to store the number of records your collapsible region contains or otherwise determine if your region needs to be expanded.

Collapsible region & hidden page item

Next, create a dynamic action that fires on page load, this will control the initial state of the region.

Expand Region - Dynamic Action

The first True action sets the value of the hidden page item. This value determines if the collapsible region has any content. In my case, this is simple - I just need to count the number of rows in the table:

Action: Set Value
Set Type: SQL Statement
SQL Statement: select count(*) from jsd_notes
Items to Submit: P20_NUM_NOTIFICATIONS

The second True action expands or collapses the region, if needed:

Action: Execute Javascript Code
Code:

 var numEntries = $v("P20_NUM_NOTIFICATIONS")
   , $region = $(this.affectedElements[0]);
  
 if (numEntries > 0 && $region.hasClass('is-collapsed') ) {
      $region.find("button.t-Button--hideShow").eq(0).click();
  }
  
 if (numEntries < 1 && $region.hasClass('is-expanded') ) {
      $region.find("button.t-Button--hideShow").eq(0).click();
  }

Affected Elements - Selection Type: Region
Region: Notifications

The JavaScript code above looks at the value of the hidden page item and if that value is greater than zero and the current state of the region is collapsed, it will find the hideShow button of the region and call the click method, causing the region to expand. The same is true for the opposite - if the region no longer contains any data and is in the expanded state, the region will collapse.

This finished functionality is shown below:

Auto Expand & Collapse Demo

Demo Here

In my demo application I also used this same dynamic action functionality to fire on dialog close and after delete of a row. This way I know the report is in the state I want it.

I am sure there are a multitude of other ways to accomplish this, but this is what worked for me. I hope it can help you as well.

- Jackie -

21 comments:

  1. Cool trick! Thanks for sharing. Nice use of ;) in the demo! :D

    ReplyDelete
    Replies
    1. Thanks! I knew someone would get a kick out of it...

      Delete
  2. Informative thanks :)

    ReplyDelete
  3. This will be a very handy trick. I will collect it.

    Thanks for sharing!

    ReplyDelete
  4. Rather than finding and clicking buttons there is a collapsible widget api that could be used. Currently undocumented but...

    $region.collapsible("expand")
    or
    $region.collapsible("collapse")

    ReplyDelete
    Replies
    1. Thanks, John - I will have a look at this :)

      Delete
    2. Seems like something that could be wrapped in a local library, until it's documented/or changed.

      Other improvement I would make is to reduce the need to ping DB again when determining row count.
      http://www.grassroots-oracle.com/2013/12/count-number-of-rows-returned-in-apex.html

      Delete
  5. Can you please share code or screenshot settings on how "delete" icon is prompting for confirmation ?

    ReplyDelete
    Replies
    1. Sure, I have a blog post in the works on this topic. Give me a couple days to finish it up and publish it.

      Delete
    2. Thanks Jackie. What I was not able to accomplish is page reload after "Delete" and prompt for "Confirm" is done. Your's is working like a charm. It should be very helpful for my reference.

      Delete
    3. Sorry it took so long - just posted it :)
      https://jackiemcilroy.blogspot.com/2018/03/delete-row-of-report-with-dynamic-action.html

      Delete
    4. Thanks Jackie. That was so helpful. It worked !!!

      Delete
    5. You are quite welcome - glad to hear you got it working :)

      Delete
    6. I have also added a dynamic action for each upload/delete to display custom message when a item is added or deleted to notify users. Now I am working on fading out those messages after 5 seconds in display.

      Delete
  6. Hi Jackie: I have a page with two select lists (one is primary and other is secondary) and rest of the page items are located below them. Based on the selection of primary list value the value in the secondary list should be null (leaving the option of choice to end user). The page itself acts like a switch. If the primary list value is 'A' then fill in the relevant page items else 'B' then fill the other page items. The issue I am facing is while doing page flip it creates two records instead of one. Is there way to keep all these changes to one record in database ?


    ReplyDelete
  7. Thanks so much, Jackie! I will use this solution a lot.

    ReplyDelete
  8. Congratulations Jackie, great trick.

    Regards.

    Jairo

    ReplyDelete
  9. Love the solution, but images are showing up as broken links

    ReplyDelete
  10. Should this work in 19.2? I have a region on page 0 that that is collapsible and this code does not seem to work.

    ReplyDelete