Refresh the parent view when a taskflow displayed in a popup returns

This post discusses an interesting use case on refreshing the parent view when an in-line popup taskflow returns. There are two taskflows, both work with separate transaction contexts(Transaction attribute is set as new-transaction). Second taskflow is invoked from the first one as a dialog. The requirement here is to refresh the 'executables' of calling page(from first taskflow) when the second taskflow returns. This scenario usually arises when the second task flow updates tables used by the first one from a different transaction context.

To learn more on taskflow, please refer Part III Creating ADF Task Flows in Fusion Middleware Fusion Developer's Guide for Oracle ADF.

Cool, now back to the use case. One possible solution for the above scenario is to define a returnListener for secondary window on the command button (which invokes second taskflow as dialog) and add the custom logic to refresh the underlying IteratorBindings used by the parent page. Last step is to manually refresh the parent view by adding it as PartialTarget - RequestContext.getCurrentInstance().addPartialTarget(returnEvent.getComponent().getParent().getParent());
That's it, job is done. I'm copying the relevant code snippet below for your reference.
<af:commandMenuItem text="Create" id="cmi1" action="create"
useWindow="true"
windowEmbedStyle="inlineDocument"
windowModalityType="applicationModal"
returnListener="#{viewScope.RefreshBean.dialogReturnListener}"
windowHeight="250" windowWidth="500"/>
public void dialogReturnListener(ReturnEvent returnEvent) {
  BindingContext bc = BindingContext.getCurrent();
  DCBindingContainer dcb =
    (DCBindingContainer)bc.getCurrentBindingsEntry();
  DCIteratorBinding iter =
    dcb.findIteratorBinding("DepartmentsView1Iterator");
  iter.executeQuery();
  RequestContext.getCurrentInstance().addPartialTarget(returnEvent.getComponent().getParent().getParent());

}

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]

How to run this sample?

Run the main.jspx. This page contains 'outer-task-flow-definition' which displays Departments details on a table. Select the 'create' menu item from the toolbar, which opens up 'inner-task-flow-definition' in a popup. Key in the new department details and click on Save. This action closes the popup and then refreshes the parent view to display new record.


Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

Comments

  1. Thanks for posting this, however there is one problem with this, you see a blank page for 1-2 seconds and then it loads the view

    May be its a ADF bug?

    Thanks,
    Harry

    ReplyDelete
  2. to be specific, second taskflow running as a Dialog with inline-popup it launches and shows blank view till pageDef executed with all data to display.

    Harry

    ReplyDelete
  3. Harry,
    This seems to be the delay in loading the task flow( server round trip + execution + loading). btw, thanks for pointing out, will try to see whether this can be optimized/fine tuned further.

    ReplyDelete
  4. Is there a way to avoid user interaction during the 1-2 sec delay during the page refresh?

    Thanks,
    Suneetha

    ReplyDelete
  5. Suneetha
    You can take a look at this post
    http://jobinesh.blogspot.com/2010/10/preventing-user-input-on-fusion-web.html
    Please see whether this helps you here

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Hi jobinesh,

    I have a scenario where the second taskflow is not shown in a popup, but is part of the parent page itself.

    If my parent page has a table, how do I refresh the table (as i don't want whole page refresh) when I am doing a save in the second taskflow..

    Any ideas ?

    Thanks

    ReplyDelete
  9. Sunil,
    One possibility is to use Contextual Events. Details can be found here-
    http://download.oracle.com/docs/cd/E15523_01/web.1111/b31974/web_adv.htm#CACJBFGI

    ReplyDelete
  10. Jobinesh,

    I am using a inline popup to solve my specific scenario. By default, it already comes with an "x" button that closes the popup. If I add the code you published in some kind of "Close" our "Save" button like you did, if the user decides to close de window by the native X button, it won't refresh the parent page. What would you suggest me do?

    ReplyDelete
  11. Daneil,
    One possibility is to embed the taskflow in your own popup and add a popupCanceledListener. Another option may be( not a gr8 solution) hide the close icon using skinning

    ReplyDelete
  12. Jobinesh,

    Thanks for the quick answer! I'm sorry, but i'm still a newbie to ADF. What do you mean when you say "embed the taskflow in my own popup"?
    Currently, I have a bounded taskflow for my inline popup (with a close function that calls a taskFlowReturn), and my home page calls this taskflow from a menu option.
    I'm gonna do some research on the listener you suggested, thanks!

    ReplyDelete
  13. Daniel,
    Please see this link -http://www.oracle.com/technetwork/developer-tools/adf/popupregionpattern-394585.pdf

    ReplyDelete
  14. Hi Jobinesh,

    In my scenario, I am calling the second taskflow as inline popup.

    The main issue that I face is to return multiple values from second taskflow to the first taskflow.

    Is there a way I can pass and receive multiple values from taskflow.

    ReplyDelete
  15. Anooj
    You can return mulitple values out of the box. Another option is wrap them in a an ArrayList and return

    ReplyDelete
  16. This comment has been removed by the author.

    ReplyDelete
  17. Hi Jobinesh,

    I am able to return multiple parameters using ArrayList.

    Can you still update me on how to return multiple values out of the box.

    ReplyDelete
  18. If I open 2nd taskflow as a default i.e Run as Dialog=false and Display Type external window then returnListener function never called. Any idea?

    Thanks in Advance.

    ReplyDelete
  19. Helo sir,
    this is Ashish

    I am working on ERP project using ADF.
    I have problem related to ReturnListener that, when User search more than 10 times on the Search form then returnListener method on parant form.

    I am not able to trace the error where it occur so please help to overcome from this situation.

    thank you.

    ReplyDelete
  20. Hi Jobinesh,

    I am trying to open a new browser window as modeless window using commandImageLink/commandButton. I have set following parameters to the above UI components

    useWindow="true"
    windowHeight="400"
    windowWidth="800"
    windowModalityType="modeless"
    windowEmbedStyle="window"

    Even though windowModalityType is stated as "modeless", new window opens as modal window.

    I am using JDeveloper 11.1.1.7. I checked in forums and found others also are facing the same issue.

    Can you point out, what is the correct way to display a modeless window?

    ReplyDelete
  21. Hi Dinesh,

    I am having the same issue with windowModalityType="modeless". Please share your thoughts if you already have the solution.

    ReplyDelete
  22. Hi,

    Below is the solution to launch modeless window

    1. Create a jspx page with the contents to be displayed in popup window
    2. In the action listener of the link/button, invoke bean method, which has below code

    public void launchPopupwindow(ActionEvent event)
    {
    //launch new window for revisions
    FacesContext context = FacesContext.getCurrentInstance();
    // Create the dialog UIViewRoot
    ViewHandler viewHandler = context.getApplication().getViewHandler();
    UIViewRoot dialog = null;
    HashMap properties = new HashMap();
    AdfFacesContext afContext = AdfFacesContext.getCurrentInstance();

    properties.put("width", new Integer(850));
    properties.put("height", new Integer(450));

    dialog = viewHandler.createView(context, );

    afContext.launchDialog(dialog, null,
    // no particular parameters
    null, // not launched from any component
    true, //show in dialog
    properties);

    }

    This will launch a seperate window for the defined dimensions

    ReplyDelete
  23. Dinesh,

    Thanks for your quick reply. I have a requirement to open a new browser window that being populated with values from the Managed bean.


    Does your solution works for non-static pages.

    ReplyDelete
  24. Hi,

    Yes. The solution works both for static and dynamic pages. Ensure the scope of the bean is properly defined.

    with best regards,
    Dinesh

    ReplyDelete
  25. Dinesh,

    Thanks for your time. It worked

    Regards
    Suren.

    ReplyDelete
  26. Dinesh,

    I have tried your solution and it worked. What if I want to open the same browser window instead of new browser window every time.

    I have tried with following code also. But it is still open new window instead of open page in the exist window.

    ExtendedRenderKitService erks =
    Service.getRenderKitService(FacesContext.getCurrentInstance(),
    ExtendedRenderKitService.class);
    StringBuilder script = new StringBuilder();
    script.append("window.open(\"" +
    "/MyApp-ViewController-context-root/faces/newSearch.jspx + "\");");
    erks.addScript(FacesContext.getCurrentInstance(), script.toString());

    I appreciate your response.

    ReplyDelete
  27. Hi,

    Do you mean opening in a seperate tab in the same window or in the same tab?

    If it is in same tab, then you have to navigate to different page using taskflows. If it is in seperate tab, try using af:showPopupBehavior. It will open the current window in a seperate tab. You have to explore ways to get your page using above two approaches.

    ReplyDelete
  28. Correction in above post.

    Use af:showPrintablePageBehavior to open the same page in seperate tab.

    Apologies.

    ReplyDelete
  29. Hi

    My scenario is ,

    I have two pages with two links.

    If i click on link in Page1 has to open new window, now if i click on link in page 2 it has to use the same opened window not the new one.

    I tried with
    script.append("window.open('").append(taskflowURL).append("', 'WorkflowDetailWindow', 'status=0,resizable=1,toolbar=0,location=0,menubar=0,width=600,height=800', true);");

    Note: If i pass the Urls (google.com) it is working fine. But if i pass the Taskflowurl then every time it is opening in new window.

    I am getting the taskflow url like below :
    String taskflowId="CountryDataTF";
    String taskflowDocument="/WEB-INF/CountryDataTF.xml";
    String taskflowURL = ControllerContext.getInstance().getTaskFlowURL(false,new TaskFlowId(taskflowDocument,taskflowId),params);

    Any suggestions please

    ReplyDelete

Post a Comment