9 Replies Latest reply: Mar 5, 2012 10:04 AM by 897507 RSS

    Creating multiple instances of a custom taskflow: how to?

    897507
      I'm using JDEV 11.1.1.5.0 and we are using WebCenter PS4.


      Our previous developer created a Schedule Countdown / Countup timer. When I try to create a copy of it from within Web Center's Mashup > Task Flows page I encounter a couple of problems:

      1. If I edit any of the task flow parameters, such as the title or the format for time (days, hours, or minutes are the options) - these changes are not reflected on the page itself. It still uses the same values as the original task Flow that I copied from.

      2. I noticed that within the Page Fragment and the Page Definition the taskFlowId is pointing to "/WEB-INF/ScheduleWidget#ScheduleWidget". The id="" is the same for every copy made from the original task flow.


      What I would like to do is have the ability to create multiple instances of this same task flow within a single space, but right now these are the only things stopping this from happening.
        • 2. Re: Creating multiple instances of a custom taskflow: how to?
          897507
          Ok thanks for the quick response.

          I'd like to leave it open if that's OK?

          I have a feeling this will circle back to how the task flows are being developed in JDev. I posted the question in the WebCenter Portal forum:

          Creating multiple instances of a custom taskflow: how to?

          Edited by: SethBW on Feb 16, 2012 12:41 PM
          • 3. Re: Creating multiple instances of a custom taskflow: how to?
            897507
            Hey Frank,

            so this issue did come full fircle. I wasn't sure at first whether it was just a bug in our app or the way that the Task Flow was coded, well because I didn't code the thing. I've done some work on it though and was able to determine that it's definitely the way that this Task Flow's javascript was coded. Originally this is how the task flow looked:
            <?xml version='1.0' encoding='UTF-8'?>
            <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
                      xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
            
                <af:resource type="javascript" source="/javascript/counter.js"/>
                <af:resource type="javascript" source="/../get/JQUERY-1.6.2.MIN.JS"/>
            
                <af:panelGroupLayout id="countdownTimer"
                                     styleClass="widgetDiv changeTimerWidgetId"
                                     visible="#{pageFlowScope.scheduleWidget.showWidget == '1'}"
                                     layout="vertical">
                                     <af:clientListener method="startScheduleWidget()" type="load"/>
                </af:panelGroupLayout>
            
                
                <af:resource type="javascript">
                    function startScheduleWidget()
                    { 
                        $(".changeTimerWidgetId").each(function(index){
                        var Countdowntimer = new cdtime($(this).attr("id"), "${pageFlowScope.counterDate}");
                        
                        Countdowntimer.setCountdown("${pageFlowScope.isCountdown}");
                        Countdowntimer.setTitle("${pageFlowScope.projectTitle}");
                        Countdowntimer.setLinkName("${pageFlowScope.linkName}");
                        Countdowntimer.setLinkURL("${pageFlowScope.linkURL}");
                        Countdowntimer.setLinkNewWindow("${pageFlowScope.linkNewWindow}");
                        Countdowntimer.setCounterResolution("${pageFlowScope.counterResolution}");
                        Countdowntimer.setCountdownText("${pageFlowScope.countdownText}");
                   
                        Countdowntimer.displaycountdown("days", formatresults);
                        });
                    }
                </af:resource>
            </jsp:root>
            The problem with this code was that the script was being placed once for each task flow we added to the page. When that happens the .each function would just overwrite every instance on the page with the last set of parameters that were called.


            Since then I've been following the documentation for handling events (http://www.orastudy.com/oradoc/selfstu/fusion/web.1111/b31973/af_event.htm#BABIDEGA), but I'm having trouble figuring out the best approach. My first thought is that pulling the JS out and accessing the instance parameters via getSource(); would be the way to go, but the documentation isn't explicit about whether you can access these parameters or not, and the event call so far has failed. I even tried following the documentation very rigidly but either the "event" is simply not passed to the function or I get an "*Object doesn't support this property or method*" error when using the following code:
            <?xml version='1.0' encoding='UTF-8'?>
            <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
                      xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
            
                <af:resource type="javascript" source="/javascript/counter.js"/>
                <af:resource type="javascript" source="/../get/JQUERY-1.6.2.MIN.JS"/>
            
                <af:panelGroupLayout id="countdownTimer"
                                     styleClass="widgetDiv changeTimerWidgetId"
                                     visible="#{pageFlowScope.scheduleWidget.showWidget == '1'}"
                                     layout="vertical">
                                     <af:clientListener method="startScheduleWidget(event)" type="load"/>
                </af:panelGroupLayout>
            </jsp:root>
            <af:resource type="javascript">
                    function startScheduleWidget(eventSrc)
                    { 
                         var targetWidget = eventSrc.getSource();
                    }
               </af:resource>
            I just want to pass the parameters of each task flow instance to a javascript function that will handle each instance separately. What am I doing wrong? I appreciate any advice you can give

            Edited by: SethBW on Feb 22, 2012 9:37 PM
            • 4. Re: Creating multiple instances of a custom taskflow: how to?
              Frank Nimphius-Oracle
              Hi,

              JavaScript doesn't know about task flows and thus doesn't isolate invocations into threads. Bottom line is that your use of JS needs to be improved.

              Actually what you do is to call a single JavaScript function, which will only exist as a single instance in the page. What you need to do instead is that for each task flow JS call, you need to create a separate JS object that then is used with that task flow. In the end you would have as many JS object instances created as task flows on a page (at the moment you don't have this and instead you use a single variable). As I see it, what you would need to do is

              - upon task flow start call JS from Java (or a region controller) to
              1. create a new object "new cdtime($(this).attr("id"), "${pageFlowScope.counterDate}");"
              2. register this object in a page variable together with a key identifying the task flow it is used with/for
              - From the task flow you then use the client listener to access the timer for this flow. E.g. you can pass an additional argument to the JS function so it knows which timer instance to get from your page level JS object registry (probably a Map)

              Frank

              Edited by: Frank Nimphius on Feb 23, 2012 10:33 AM
              • 5. Re: Creating multiple instances of a custom taskflow: how to?
                897507
                Thank you for sending me in the right direction. So are you saying that I cannot simply pass the event object to my function to determine the source? At one point I was able to accomplish this, but the getSource(); function failed when trying to access it's methods and variables (I got an "Object does not support this method" error).

                I did not code this so I understand the need for cleaning up the JS - I am actually coming from a front end development background learning ADF and JDev, so far I just am having trouble finding how to pass the originating object (the panelGroupLayout div that is created). Is there an example anywhere on this?

                I have been reading the Web User Interface Developer's Guide but the details are hazy - it did not mention that I could not pass the "event" from the task flow's clientListener to my JS function. I was even searching for how to create a unique key for each instance of this task flow in ADF, but have not found anything.
                - upon task flow start call JS from Java (or a region controller)...
                - I'm sorry - isn't this what we are doing here?:
                <af:clientListener method="startScheduleWidget()" type="load"/>
                I really appreciate any advice.

                Edited by: SethBW on Feb 23, 2012 10:51 AM
                • 6. Re: Creating multiple instances of a custom taskflow: how to?
                  Frank Nimphius-Oracle
                  Hi,

                  a golden rule in JavaServer Faces and ADF Faces is to not think in markup but component. So instead of accessing a DIV element, access the component instance on the browser client. A component exposed on a task flow provides a reference to JavaScript through the JavaScript component event

                  function myFunction(event){
                  var componentInstance = event.getSource();
                  ... access component instance properties etc
                  }

                  The unique name you are looking for is he clientId as each task flow that is exposed in an ADF Region resides in a naming container that adds the container ID to the client ID of the component

                  var clientId = componentInstance.getClientId();

                  more ADF Faces JS APIs: http://docs.oracle.com/cd/E21764_01/apirefs.1111/e12046/toc.htm

                  Frank
                  • 7. Re: Creating multiple instances of a custom taskflow: how to?
                    897507
                    Hi Frank. Thanks again for your help teaching me with this type of issue. I found this:
                    http://jobinesh.blogspot.com/2011/03/passing-dynamic-parameters-to-java.html

                    Does this sound accurate for what we're trying to accomplish? I saw he mentions you in his post.
                    • 8. Re: Creating multiple instances of a custom taskflow: how to?
                      Frank Nimphius-Oracle
                      Hi,

                      from the code you posted so far it seems as if you require client side JavaScritpt objects per each task flow instance.

                      Frank
                      • 9. Re: Creating multiple instances of a custom taskflow: how to?
                        897507
                        I understand that we need the ability to target each task-flow/component individually. That is not the problem I am having. I just am having trouble finding documentation or examples of any of the methods you mentioned above - specifically I cannot find instructions or methods that show me how to pass the component to the JS, or to register the object in a page variable together with a key that identifies the task flow (mapping).
                        Frank Nimphius wrote:
                        - upon task flow start call JS from Java (or a region controller) to
                        1. create a new object "new cdtime($(this).attr("id"), "${pageFlowScope.counterDate}");"
                        2. register this object in a page variable together with a key identifying the task flow it is used with/for
                        - From the task flow you then use the client listener to access the timer for this flow. E.g. you can pass an additional argument to the JS function so it knows which timer instance to get from your page level JS object registry (probably a Map)-
                        Sorry if my question was confusing, I am unable to find how to send any reference of the component/task flow to the JS.

                        Would it not be easiest to simply send the reference/key directly to each JS object as you mentioned VS. creating a map?

                        Edited by: SethBW on Mar 5, 2012 10:02 AM