Monday, January 13, 2014

Stopping Dynamic Actions using apex.da.cancelEvent

Update: Nick Buytaert wrote a follow-up article on the apex.da.resume function. I suggest reading it along with this article in case you need to resume a Dynamic Action (which is especially useful for plugins).

They're a few times when you may need to stop a Dynamic Action part way through the executing all its actions. Since individual actions don't have conditions associated with them there's no supported way to do this. Thankfully there's an undocumented JavaScript (JS) function called apex.da.cancelEvent. Here's an example of how to use it:

Suppose you have a page with two items, P1_X and P1_Y, and a button on P1. When the user clicks the button the Dynamic Action (DA) needs to set P1_X = X and P1_Y = Y. The DA setup will look like the following:


When you click the button P1_X and P1_Y are set to X and Y respectively. 

Now suppose that after P1_X is set you wanted to stop all other actions in the DA (in this case setting P1_Y). There's no way to declaratively do this. Instead you must use the apex.da.cancelEvent function. 

Add a new JavaScript "True Action" to the existing DA with sequence 15 (so its between the two other actions). In the code section use: apex.da.cancelEvent.call(this);  Be sure to uncheck the "Fire On Page Load" option. The updated DA will look like image below (the new action is highlighted).


If you refresh P1 and click the button associated to this DA only P1_X will be set. The third action in this DA will not be executed.

The above example probably isn't the best use case for leveraging apex.da.cancelEvent however it does highlight its functionality. It is useful if you create your own custom confirm notice or some other process that determines if the rest of the actions in a DA can occur.

Note: You'll notice that I used the additional call() function when calling apex.da.cancelEvent in the action. Calling it defines the value of this in the function call as it is required in the cancelEvent function. For more information please read the JS call() documentation.

4 comments:

  1. Martin,

    in this particular case wouldn't be an option to user Cancel Event, which will do the same as apex.da.cancelEvent.call in your example?

    So in some cases there as an official/declarative way to this this. But as it states in documentation you can use
    this in limited situations.



    http://docs.oracle.com/cd/E37097_01/doc/doc.42/e35125/advnc_dynamic_actions.htm#CIHCFDGB

    Miscellaneous

    Cancel Event - Cancels subsequent dynamic actions or events from firing, based on certain conditions. This could be useful in the following situations:

    If you have multiple dynamic actions on a page that are based on the same event (such as Click) and they refer to the same element on the page, you can use the Cancel Event action to prevent subsequent dynamic actions from firing, conditionally based on its When Condition.

    If a dynamic action has many true actions, you can use Cancel Event to halt subsequent actions from being processed. Currently this has limited value as it is not possible to define a dynamic action's actions to fire conditionally, so this would just always prevent subsequent actions being processed, which could be useful in debugging.

    Used to cancel page submission, when used with the Before Page Submit event of dynamic actions. For example, suppose you define a dynamic action that fires on the Before Page Submit even. For the Condition, you define JavaScript Expression and in the Value enter an expression such as $v('P2_ENAME') == 'DO NOT SUBMIT'. Then, if you define a True Action that uses the Cancel Event action, the page is not submitted when the ENAME field is equal to DO NOT SUBMIT.


    Regards,
    Aljaz

    ReplyDelete
    Replies
    1. Hi Aljaz,

      You're right, there is an action to do this. There is one catch: you can not apply a specific condition on it (i.e. it will always be executed as part of the Dynamic Action set). For example, in the above demo, how would you conditionally run the Cancel Event action as part of sequence 15?

      apex.da.cancelEvent allows you to specifically control when to cancel the rest of the actions within the Dynamic Action.

      I don't recommend using it all the time, rather just for the specific cases when you need it.

      Martin

      Delete
  2. Hi Martin,

    Just a note on the usage of apex.da.cancelEvent.call(this); which I noticed:
    When used as part of a (complex) JavaScript inside of an action, the current action will still be executed until finished, but the NEXT action(s) will not be executed anymore.

    Christian

    ReplyDelete
  3. Thank you Martin. This is a very handy technique. It works like a charm in APEX 5.0 with jQuery Mobile 1.4.

    ReplyDelete