Sunday, March 18, 2018

Delete a Row of a Report with a Dynamic Action

I was asked recently how I implemented the deleting of a row in my demo application, so I thought I would post the answer here in case anyone else was curious.

To accomplish the deletion of a row with a prompt to the user for confirmation you will need a hidden page item and a dynamic action.

On the page that has your report, add a hidden page item - mine is called P20_DELETE_ID. This item will be used by our dynamic action to hold the primary key of the row on which the user clicked the delete icon.

You need to add a link column to your report for the delete icon with the following attributes:

Link Target: URL
URL: javascript:void(null);
Link Text: <span class="t-Icon fa fa-trash delete-note" aria-hidden="true"></span>
Link Attributes: data-id=#REMOVE#
Link Column

Notice in the Link Text that I added a class called delete-note. This is the jQuery selector we will use to trigger our dynamic action. Also, notice the Link Attributes - the column referenced here, in my case #REMOVE#, should hold the primary key for the row. This value will be used to identify the row that needs to be deleted in your delete PL/SQL statement.

Next, we need a dynamic action that fires on click of our jQuery selector, .delete-note. This action will have four true actions:
Delete Row Dynamic Action

True Action #1: Confirm
Text: Are you sure?
Confirm

True Action #2: Set Value
Settings:
Set Type: JavaScript Expression
JavaScript Expression: $(this.triggeringElement).parent().data('id')
Affected elements:
Selection Type: Item(s)
Items(s): P20_DELETE_ID <---- your hidden page item
Set Value

True Action #3: Execute PL/SQL Code
PL/SQL Code: delete from jsd_notes where id = :P20_DELETE_ID;
Items to Submit: P20_DELETE_ID <---- your hidden page item
Execute PL/SQL Code

True Action #4: Refresh
Selection Type: Region
Region: Notifications <---- your report region
Refresh

And that should do it :)


- Jackie -

Sunday, September 24, 2017

Build Options & Agile Development

Build Options are a really powerful feature of APEX that gives developers a lot of flexibility, especially when doing Agile development. They allow you to control the contents of an application that is displayed at run-time. As an Agile APEX developer, what do you do as the current sprint is winding down and some developers need to start moving on to the contents of the next sprint in order to keep busy? You don’t want your developers sitting idle, but you can’t create a release for the current sprint until all the work is done - and you also can’t release Sprint 1 if it contains unfinished Sprint 2 content. As long as your sprint contents can be easily separated, i.e. you aren’t reworking the same component in each sprint; the simple solution is to create build options that correspond to your sprints. By consistently assigning the build options to the components you develop during a sprint, you create an easy mechanism to ‘turn off’ parts of the application at run-time. Developers can work on both Sprint 1 and Sprint 2 contents simultaneously, and when the application is exported for the Sprint 1 release, you can effectively set all Sprint 2 content to be excluded. When the Sprint 1 application is installed in another environment and a user runs the application, they will be none-the-wiser that any Sprint 2 contents has been developed.

Build Options can be found under Shared Components in the Security section. When you create a build option you have a couple of choices. First, you will have to give it a name. If doing Agile development, I name them after the sprints using Sprint 1, Sprint 2, etc.

Sprint 1 - Include

Next, you will need to chose the Status. You have two options, Include or Exclude. This status will be set for the current environment. Choose Include if, when you run the application, you would like to see the features that correspond to this build option. Choose Exclude if, when you run the application, you want to hide the features that correspond to this build option. Keep in mind this only excludes the feature from being shown at run-time; you will still be able to see the components in the page designer. I set this to Include as I like to be able to see the changes I am making to the application when I run it in development.

Now, you will need to decide on the Default on Export status. This option determines if the build option will be included or excluded when the application is exported. This feature is key for working with sprints. I set the current sprint and all prior sprints to Include. All future sprints should be set to Exclude, this ensures that when the application is exported and imported in to a new environment only the contents of the finished sprints are visible to the end-user.

Sprint 2 - Exclude

Maybe the most important step is to assign the build options as you develop. You can set the Build Option in the Configuration section of a component and you can assign them to pretty much any component: pages, page items, computations, validations, dynamic actions, page processes… the list goes on. If you need to check the status of build options within PL/SQL code, take a look at this article by Martin Giffy D’Souza or if that isn’t enough control, there is always conditional compilation of the database schema as described by Jeff Kemp.

Select a Build Option

Once all of your build options are assigned and your sprints have the proper Include/Export status - you are all set. If you ever want to test what the application will look like with a certain Build Option excluded, simply switch the Status for that build option to Exclude and run the application.

You can even take things a step further and document the application components belonging to each sprint/build option by querying the data dictionary. This query can be turned into a report that can then be printed (with APEX Office Print, of course) and included in your sprint release notes.

- Jackie -

Thursday, July 20, 2017

Adding a Modal Template to a Legacy Theme in APEX 5

Modal dialogs are a native feature in APEX 5. Unfortunately for some users, although they have upgraded to APEX 5 they are still using an older theme that does not support native modals. Most developers get a bit discouraged when they think they can easily create a modal page, but because of their theme they find that the Modal Dialog and Non-Modal Dialog Page Mode options are disabled when trying to create a new page.

Modal Dialog Option Disabled

To enable these options, you need to modify your theme to contain a Modal Dialog template. To make things easier, I copy the Popup template as a starting point. Just go to Shared Components > Templates and search for the Popup page template. Click on the copy icon and in the wizard, give the new template a name, I called mine Modal.
Shared Components > Templates

Once your modal template is created, edit it and change the Template Type from Normal Page to Dialog Page.
Template Type

Next, scroll down to the Javascript section and enter the following (these are the default values that can be found by examining the help text of the items):

Dialog Initialization Code:

apex.navigation.dialog(#PAGE_URL#,{title:#TITLE#,height:#DIALOG_HEIGHT#
     ,width:#DIALOG_WIDTH#,maxWidth:#DIALOG_MAX_WIDTH#,modal:#IS_MODAL#
     ,dialog:#DIALOG#,#DIALOG_ATTRIBUTES#},#DIALOG_CSS_CLASSES#,#TRIGGERING_ELEMENT#);

Dialog Closure Code:

apex.navigation.dialog.close(#IS_MODAL#,#TARGET#);

Dialog Cancel Code:

apex.navigation.dialog.cancel(#IS_MODAL#);

Now, you will want to apply your changes. Your new modal template is now done, but if you were to try and create a modal page at this point, you would still find that the Modal Dialog Page Mode option is disabled. To fix this, you need to update your theme properties to reference your new modal template.

Navigate to Shared Components > Themes and click on the name of your current theme.
Shared Components > Themes

Move to the Dialog Defaults section and set the Dialog Page to the name of your new template, in this case Modal. You can also select the default templates for the Dialog Content Region and Button Regions, if you know what you would like to set them to.
Dialog Defaults

At this point, the Modal Dialog option will be enabled in the page creation wizard. Give it a try!

-Jackie-

P.S. While this solution will work in a pinch - you really should, at least, consider moving to the Universal Theme. Check out all of the reasons why here.

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 -