Wednesday, January 19, 2011

Working together: Save Before Exit and Tabular Forms

The SkillBuilders Save Before Exit plug-in is designed to make it very easy for developers to help prevent end users from loosing changes to work they’ve done on a page. When a user leaves a page it runs some checks to find out if changes have been made but not saved. If it finds any, it prompts the user before allowing them to go to the next page. If you’re not familiar with the plug-in, you can find it here along with the rest of our plug-in offerings.

Tabular Forms now have a similar technology built in – which is very clever. It’s needed in Tabular Forms because there are some built in controls, such as header sorting links and pagination links, that  when used could result in end users losing their work. The built in functionality that helps prevent this works great, it even highlights the cells that have changed (perhaps I’ll add that to the plug-in).

Recently, two separate users of the SkillBuilders Save Before Exit plug-in let me know of some problems they encountered while integrating the plug-in with the built in Tabular Form functionality. After having been a little confused myself at first, I was delighted to learn that both can coexist quite nicely – even compliment each other.

Here are some guidelines to properly integrate the two:

  1. Enable Partial Page Rendering (PPR) for the Tabular Form. This setting can be found under Layout and Pagination in the Report Attributes. PPR allows the tabular form to sort and paginate without causing the entire page to refresh. This prevents the plug-in from doing anything in these cases. The built in functionality will continue to work with PPR enabled.
  2. Make sure that the sorting links, pagination links, as well as the “Add” button of the Tabular Form are NOT selected in the No Warning Selector attribute of the plug-in. Again, since PPR is preventing the page from reloading it is not necessary to include these elements. In fact, including them can even cause an issue that prevents the plug-in from working when it should.

    Warning: the default No Warning Selector will include the Add button so make sure to change this. You’ll need to explicitly select the buttons and/or other elements that should allow a user to leave without being warned of unsaved changes.

So how do these two compliment each other? The warning functionality built into Tabular Forms only works when sorting or paginating through the report. But if the user clicks a breadcrumb or closes the browser, then changes will be lost. The plug-in can be used to give the user one last chance to save their changes.

Monday, January 17, 2011

Saving Current Values with Cascading LOVs

A friend, Monty Latiolais, recently asked an interesting question regarding cascading LOVs:

Say you've got two LOVs...STATES and CITIES. They both default to 'ALL' and 'ALL'. Since CITIES is dependent on STATES, as soon as STATES is changed, CITIES is blanked out. What should happen is that CITIES gets re-evaluated as in the following example... let's say STATES is ALL and CITIES is "Houston". If one then changes STATES to "Texas", CITIES should remain "Houston" as that is a valid value for CITIES.

So basically, is it possible to maintain the selected value of an item if that same value exists in the list of values after refreshing? That’s a great question! Thanks to new events in the APEX framework and Dynamic Actions the solution is far easier than it would have been in the past!

Click here to see the demo but continue reading to learn how it all works…

There are a three main events you need to be concerned with when it comes to cascading selects:

  • change
  • apexbeforerefresh
  • apexafterrefresh

The change event is a standard part of JavaScript and the DOM. This event fires when the user manually changes the value of the select list but can also be triggered programmatically via JavaScript. The apexbeforerefresh and apexafterrefresh events are custom events in the APEX framework. They fire just before and just after AJAX requests refresh something on the page. The events work with many items and regions that utilize this technology.

In this example we have two select lists: parent and child. If you change the value of the child select list then the change event will fire and that’s it. But if you change the value of the parent select list a lot more happens to the child select. Here are some of the highlights:

  1. The current LOV values are cleared out
  2. The apexbeforerefresh event is triggered
  3. An AJAX request brings back new values. This only happens if
    1. optimize refresh is set to false
    2. optimize refresh is set to true and all parent items are not null
  4. The apexafterrefresh event is triggered
  5. The change event is fired

Now, knowing all of this, how can we utilize the sequence of events to solve the original problem of keeping selected values? The answer lies in creating two dynamic actions.

The first dynamic action will store the current value of the select list so that we can access it later. This will typically happen when the change event fires but it will also happen when the page first loads. Here’s how to create the first Dynamic Action:

  1. Right click the child select list and select Creation Dynamic Action.
  2. Select Advanced.
  3. Click Next >.
  4. Enter a name for the first Dynamic Action.
  5. Click Next >.
  6. Set Event to Change.
  7. Click Next >.
  8. Set Action to Execute JavaScript Code.
  9. Set Code to: $(this.triggeringElement).attr('data-last-value', $(this.triggeringElement).val());
  10. Click Next >.
  11. Click Create.

The second Dynamic Action will take advantage of the apexafterrefresh event and access the previously stored value. That value will then be used to look through the new options and if a match is found it will be selected. Here’s how to create the second Dynamic Action.

  1. Right click the item (again) and select Create Dynamic Action.
  2. Select Advanced.
  3. Click Next >.
  4. Enter a name for the second Dynamic Action.
  5. Click Next >.
  6. Set Event to After Refresh.
  7. Click Next >.
  8. Set Action to Execute JavaScript Code.
  9. Set Code to: $(this.triggeringElement).children('option[value="' + $(this.triggeringElement).attr('data-last-value') + '"]').attr('selected','selected');
  10. Click Next >.
  11. Click Create.

So two lines of actual code, not bad at all!

Thursday, January 13, 2011

Plug-in Update: SkillBuilders Super LOV 1.2

The APEX community has been providing us with lots of great feedback on Super LOV thus far... Keep it coming and we’ll keep making it better!

This release includes the following changes:

  1. Integrated buttons in the main input. The buttons are styled using jQuery UI which is consistent with the rest of the plug-in. Also, the “clear” button switches to a confirmation button to help prevent accidental clearing.
  2. Added “Effects Speed” attribute. Many people have had great things to say about the transition effects implemented in Super LOV but some people complained they were too slow for heavy data entry. Now you can adjust the speed to make it faster or set it to instant which essentially disables the effects altogether.
  3. Added “Default Search Column Number” attribute. Currently this will just default the column that is searched when the modal dialog is opened. This attribute will become even more important with the next release – when the item can be made “enterable”.
  4. Fixed bug that prevented Cascading LOV attribute from working. The item now “cascades” as it should with both parent and child items.

Future plans include:

  1. Making the input “enterable”. This will allow a user to focus in the main input and begin typing. If a single match is retrieved in the LOV, then the hidden item will be updated and the LOV will never open. If multiple matches are found then the LOV will open “pre-filtered” to allow for selection.
  2. Allowing LOV selection to update multiple items/elements. Lot’s of people (especially those from Oracle Forms) have been requesting this functionality so we’ve added it to the list.

To get this plug-in, as well as our other plug-in offerings, visit new “Plug-ins” page at Future plug-in releases, including this one, must be downloaded from that site. Downloads require free registration, but it’s a small price to pay for some great functionality. Smile Enjoy!