Thursday Feb 12, 2015

How-to open and close a popup dialog from Java in MAF

MAF Version: 2.1

Problem Statement

In MAF, application developers use two component behavior tags, amx:showPopupBehavior and amx:closePopupBehavior, to show or hide popup dialogs in response to user interaction, pressing a command button or link. What however if you need to show or hide a popup from Java in a value change listener or similar component event? And what if the dialog should close itself after a period of time? By the time of writing, no API for this exists in MAF.

The Solution

Since there is no framework API to close and open popup dialogs in MAF, a custom implementation must do. The custom implementation uses JavaScript, as well as the amx:showPopupBehavior and amx:closePopupBehavior tags on hidden buttons (visible buttons would be possible too).

To show or hide a popup dialog you use Java in a managed bean to call out to JavaScript,using the
AdfmfContainerUtilities.invokeContainerJavaScriptFunction() framework method.

Section Q&A:

Q1: Could you call the same from a POJO Data Control?
A1:Yes you can.

Q2: Does it make sense?
A2: No. The data control is part pf the MAF model and thus needs to be generic and not specifically written for a view in MAF. 

About the Example Code

The MAF 2.1 sample code shown in this blog entry (and available for download) keeps it simple. The AMX page displays single command button that, when pressed, triggers a component action event. This action event is calls a Java method in a managed bean that in turn invokes JavaScript to "virtually" press the hidden button with the amx:showPopupBehavior tag attached to it for you. A timer in the same managed bean then waits for 5 seconds before it closes the dialog, pressing the other hidden button (it actually raises a tap event on teh button). Its a simple example that however showcases nicely how you can open and clode dialogs in MAF.

The Sample Implementation

Though you can download the sample ZIP file from a link provided at the end of this article, its worth showing the code in the blog entry as well, so you you can quickly scan it. The JavaScript source is saved in a stand-alone JS file so it can be reused. In general I recommend using external JavaScript files and force yourself to write generic code than to stuff scripts into an AMX page directly.

Step 1) Creating the JavaScript file

First you need to create JavaScript file - or extend an existing file - with the JavaScript code shown below. In my sample (MAF 2.1) this the JS file is named "PopupUtils.js". The two functions in the file popupUtilsShowPopup and popupUtilsHidePopup become globally available for the feature they are configured for (explained next). The two functions require a singel argument to be passed, which is the id of the popup dialog to close

(function () {
  //register 
  popupUtilsShowPopup = function() {
        //the argument is required and cannot be missing
        if (arguments.length > 0) {
            var popupOpener = document.getElementById(arguments[0]);
            if (popupOpener != null && popupOpener != undefined) {
                adf.mf.api.amx.triggerBubbleEventListener(popupOpener,"tap");
            }
            else {
                adf.mf.log.Application.logp(adf.mf.log.level.WARNING,
                  "PopupUtils", "showPopup", "hidden button to launch
                   popup not found");
            }
        }
        else {
            adf.mf.log.Application.logp(adf.mf.log.level.WARNING,
              "PopupUtils", "showPopup", "Missing input argument");
        }
    }

    popupUtilsHidePopup = function() {
        //the argument is required and cannot be missing
        if (arguments.length > 0) {
            var popupCloser = document.getElementById(arguments[0]);

            if (popupCloser != null && popupCloser != undefined) {
                adf.mf.api.amx.triggerBubbleEventListener(popupCloser,"tap");
            }
            else {
                adf.mf.log.Application.logp(adf.mf.log.level.WARNING,
                "PopupUtils","showPopup", "hidden button to close popup
                 not found");
            }
        }
        else {
            adf.mf.log.Application.logp(adf.mf.log.level.WARNING,
             "PopupUtils", "hidePopup", "Missing input argument");
        }
    }

})();

Step 2) Registering the JS file with a MAF feature

To register the JavaScript file with a MAF feature, open the maf-feature.xml file (the file resides in the View Controller| Application Sources || META-INF directory). In the opened maf-feature.xml file, select the feature that needs programmatic access to a popup and select the "Content" tab. Click the green plus icon next to the "Includes" label and search for the JavaScript file in the project. The file type should be set to "JavaScript".

With this configuration, the custom JavaScript functions become available so they can be called from AdfmfContainerUtilities.invokeContainerJavaScriptFunction()

Step 3) About the Managed Bean (Java)

A managed bean is useed to hold the Java code that either launches or closes the popup. The managed bean doesn't hold state and therefore can be defined in any scope (shorter scopes are preferred). The sample actually shows and hides the popup in response to an action performed on another button. However, you can call the same code from any other component event, e.g. from a value change listener.

public class PopupHelper {

    boolean isPopupOpen = false;

    public PopupHelper() {

    }

    public void onPopupShowHideAction(ActionEvent actionEvent) {

        if (!isPopupOpen) {

         //the error object is filled with the reason for a JS exception.
         //If the variable is empty, no exception has occured. Note that
         //usually you use the return object to pass information from the
         //JS function back to MAF. In this case, the function doesn't
         //return a value and so its only used here to allow debugging
         //of exceptions

            Object errorMsg =
                AdfmfContainerUtilities.invokeContainerJavaScriptFunction
                (FeatureContext.getCurrentFeatureId(),"popupUtilsShowPopup",
                new Object[] {"_popShowId" });


            isPopupOpen = true;

            //wait a few seconds and then close the popup
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                  closePopup();
                  this.cancel();
                }

            },5000);

        }
            }


    private void closePopup() {

        if (isPopupOpen) {

            Object errorMsg =
               AdfmfContainerUtilities.invokeContainerJavaScriptFunction(
                FeatureContext.getCurrentFeatureId(),"popupUtilsHidePopup",
                new Object[] {"_popCloseId" });
            isPopupOpen = false;

        }

    }
}

Step 4) Configuring the hidden buttons

The hidden buttons (in this example they are hidden, but can be visible too) have the two behavior tags, amx:showPopupBehavior and amx:closePopupBehavior defined as shown in the AMX page source shown below

<amx:panelPage>
 ...
  <amx:commandButton text="_hiddenShow" id="_popShowId"
                     inlineStyle="visibility: hidden;">
      <amx:showPopupBehavior id="spb1" popupId="p1"
                        type="action" decoration="simple" alignId="pp1"
                        align="overlapMiddleCenter"/>
  </amx:commandButton>
  <amx:commandButton text="_hiddenClose" id="_popCloseId"
                      inlineStyle="visibility: hidden;">
      <amx:closePopupBehavior id="cpb1" popupId="p1"
                                     type="action"/>
  </amx:commandButton>



  <amx:commandButton text="Show / Hide Popup" id="cb3"
                     actionListener="#{PopupHelper.onPopupShowHideAction}"/>

</amx:panelPage>
  <amx:popup id="p1" autoDismiss="false"
          inlineStyle="font-size:large;">
          <amx:outputText value="This Popup is launched from Java in a
                         managed bean. Wait 5 seconds for Java to close
                          this dialog." id="ot2"/>
</amx:popup> 

Download Sample

The sample files can be downloaded in a MAF 2.1 workspace from here: http://www.oracle.com/technetwork/developer-tools/adf/learnmore/programmaticcloseofpopup-2420222.zip Run the AMX page within the sample workspace and press the command button in the opened mobile application. A dialog shows and stay up for 5 seconds before it closes down again.

Note:  If you experience problems, or like to comment on the solution, please post to the MAF forum on OTN: https://community.oracle.com/community/oracle-mobile/oraclemaf/content?customTheme=otn

Tuesday Dec 04, 2012

Oracle Brings Java to iOS Devices (and Android too)

Java developer, did you ever wish that you can take your Java skills and apply them to building applications for iOS mobile devices?

Well, now you can!

With the new Oracle ADF Mobile solution, Oracle has created a unique technology that allows developers to use the Java language and develop applications that install and run on both iOS and Android mobile devices.

The solution is based on a thin native container that installs as part of your application. The container is able to run the same application you develop unchanged on both Android and iOS devices.

One part of the container is a headless lightweight JVM based on the Java ME CDC technology. This allows the execution of Java code on your mobile device. Java is used for building business logic, accessing local SQLite encrypted database, and invoking and interacting with remote services.

Java concept on the UI too

To further help transition Java developers to mobile developers, ADF Mobile borrows familiar concepts from the world of JSF to make the UI development experience simpler.

The user interface layer of Oracle ADF Mobile is rendered with HTML5 which delivers native user experience on the devices, including animations and gesture support. Using a set of rich components, developers can create mobile pages without needing to write low level HTML5 and JavaScript code. The components cover everything from simple controls such as text fields, date pickers, buttons and links, to advanced data visualization components such as graphs, gauges and maps, and including unique mobile UI patterns such as lists, and toggle selectors. Want to see the components in action? Access this demo instance from your mobile device. Need to further customize the look and feel? You can use CSS3 to achieve this.

A controller layer - similar in functionality to the JSF controller - allows developer to simplify the way they build navigation between pages. The logic behind the pages is written in managed beans with various scopes – again similar to the JSF approach.

Need to interact with device features like camera, SMS, Contacts etc?

Oracle conveniently packaged access to these services in a set of services that you can just drag and drop into your pages as buttons and links, or code into your managed beans Java calls to activate. Underneath the covers this layer is implemented using the open source phonegap solution.

With the new Oracle ADF Mobile solution, transferring your Java skills into the Mobile world has become much easier. Check out this development experience demo.

And then go and download JDeveloper and the ADF Mobile extension and try it out on your own. For more on ADF Mobile, see the ADF Mobile OTN page.

About

This blog is is dedicated to announcements,tips and tricks and other items related to developing, integrating, securing, and managing mobile applications using Oracle's Mobile Platform. It is created and maintained by the Oracle Mobile product development team.

Archive of past entries

Even More Mobile Development Blogs

Oracle A-Team Site - Mobile Related Entries

Code samples from the Community

Fusion Middleware Blogs

Search

Archives
« March 2015
SunMonTueWedThuFriSat
1
2
3
5
6
7
8
9
10
11
12
13
14
15
17
18
19
20
21
22
23
24
25
26
27
28
29
31
    
       
Today