Saturday, March 12, 2016

Launch Popup while loading the page

Problem Description: In this blog I am trying to explain how we can launch a popup while loading the page. Generally we launch popup as an event of some activity (button click, link click, input change etc). What if we need to launch a popup while user is launching the page first time? There are different usecase for this.
a. You may want to provide a change password popup to user when he access system first time.
b. You may want to ask user to 'read and acknowledge' agreement terms before accessing a page.


Solution: There could be multiple ways to do it. I am going to show two ways.
First which works if you have a page and your UI components are directly on page.
Second if you have bounded task-flow and your popup is on a jsff of bounded task-flow. Task-flow is appearing as a region on main page.


First Approach: When you have your UI components (popup) on a jspx page directly.

Step 1: Create your page (say main.jspx) and bean (say MainBean.java) and register it in backingbeanscope.

Step 2: Create popup on your main.jspx

Step 3: Bind popup with bean

Step 4: Implement BeforePhase for your page: For this you need to select f:view tag in your page and set(or create) bean method that you want to execute in beforePhase property.

Step 5: Implement launchMyPopup method as shown below
    public void launchMyPopup(PhaseEvent phaseEvent) {
        // Add event code here...
        if(this.getChangePwdPopup() != null){
            Map viewScope = (Map)ADFUtil.evaluateEL("#{viewScope}");
            String isPgInitialized = (String)viewScope.get("pIsPgInitialized");
            if(isPgInitialized == null){

               //You may want to have additional complex business logic of page initialization. Do it here.
                    this.getChangePwdPopup().show(new RichPopup.PopupHints());
                viewScope.put("pIsPgInitialized", "Y");
                
            }
            
        }
        
    }

Above code is going to get executed while page is loading. It is actually going to get executed multiple times while page is getting loaded. (For every phase once).
Out logic is we are going to do page initialization activities (in this case launching popup) only once and immediately we will set a viewScope parameter. To avoid unnecessarily running page initialization code again and again in every phase, we are going to check if viewScope parameter is already set. If its there we will not execute our code. Viewscope checking will save us if user is doing some activity like button click etc on page, still our code is not going to execute as viewScope will still have the variable.

Step 6: Run page and verify.


Now coming to next approach. If your popup is on a jsff, which is used in a bounded-task-flow. You have dropped bounded task-flow as a region on main page.

In this situation, we don't have beforePhase property in jsff file component. One easy solution that I can figure out is having a hidden (visible=false) outputtext on page. Bind it on bean and write your code inside getter method.


Step 1: Have your task-flow (say MyTestFlow), bean (MainFGBean registered in task-flow at backingbeanscope), Fragment (say MyTestPG.jsff).

Step 2: Create popup in MyTestPG.jsff and bind it with bean

Step 3. Have one hidden (visible=false) outputtext in jsff file. It must be at very bottom of jsff. That will make sure that getter of this run at last. By the time all UI component would have been already bound with bean.

Step 4. Have below code in your bean

public class MainFGBean {
    private RichPopup changePwdPopup;
    private RichOutputText pageInitText;

    public void setChangePwdPopup(RichPopup changePwdPopup) {
        this.changePwdPopup = changePwdPopup;
    }

    public RichPopup getChangePwdPopup() {
        return changePwdPopup;
    }
    public void setPageInitText(RichOutputText pageInitText) {
        this.pageInitText = pageInitText;
    }

    public RichOutputText getPageInitText() {
        if(this.getChangePwdPopup() != null){
            Map viewScope = (Map)ADFUtil.evaluateEL("#{viewScope}");
            String isPgInitialized = (String)viewScope.get("pIsPgInitialized");
            if(isPgInitialized == null){

                //You may want to have additional complex business logic of page initialization. Do it here.
                this.getChangePwdPopup().show(new RichPopup.PopupHints());
                viewScope.put("pIsPgInitialized", "Y");
                
            }
            
        }
        return pageInitText;
    }
}

NOTE: How getPageInitText is launching popup. Its trying to initialize page UI components. By the time this getter runs popup getter/setter is already done and popup is already associated with bean. That is because you have added outputtext at the bottom of jsff.

Step 5: Run and test. 


NOTE: Above mentioned approaches are not limited to showing poup on page-load but it is helpful to play around with UI components on page load. For example
a. You may want to make your complete page read only for certain condition.
b. You may want to dynamically make one column form to two column based on some condition.

To sumup you want to play with UI components while page is getting loaded.