Is there a way to stop actions from firing in Summer '14?

  • 5
  • Question
  • Updated 4 years ago
  • Answered
  • (Edited)
Congrats to the team on the release of Summer '14 RC - Features are looking great!  

Regarding the new Actions available on Models, Buttons, etc., is there a way to stop further actions from occurring from within an action?

For example:

Page Title Button has a multiple actions assigned
Action 1 - Run snippet
Action 2 - Run snippet/Save Model/etc.

Questions:
1) Is there a way to ensure that Action 2 does not get called if Action 1 fails?  If I "throw" out of Action 1, Action 2 will not get called but then a javascript exception goes unhandled.

2) Along these lines, if Action 1 is a stock skuid action (e.g. save models), what happens to actions that follow if the action fails?  It appears that if the Action is "Save Models" and it fails, no further actions are triggered.  Correct?  if yes, is this true of all stock actions where if it fails, further actions will not be triggered?

The use case is as follows:
Action 1 - Validate certain data points on models (e.g. business rules essentially).  If validation fails, I do not want the Save to occur.
Action 2 - Save models

Thank you!
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb

Posted 4 years ago

  • 5
Photo of Zach McElrath

Zach McElrath, Employee

  • 48,984 Points 20k badge 2x thumb
Barry,

There is a way to do it, we will be responding by the end of the week.

Zach
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Great news, thanks Zach!
Photo of Zach McElrath

Zach McElrath, Employee

  • 48,984 Points 20k badge 2x thumb
There are two ways to stop actions from firing from a Snippet:

(a) [Available as of Skuid 5.4, which is now available] Return false from your Snippet. This will cause the Action Framework to check for On-Error Actions defined for the current Action, and run that sequence of On-Error Actions, and NOT run any successive actions.

Example: From a Wizard Step Button, you might want to validate that all Required Fields have been filled out before navigating to the next step, or performing some other actions in the action framework. Here is an example Snippet that would do this, validating Required Fields on an Account and Contact Model being created in the current step:

var params = arguments[0],    
    step = params.step,
    stepEditor = step.editor,
    $ = skuid.$;
// Clear our list of messages
stepEditor.clearMessages();
var models = [
   skuid.model.getModel("Account"),
   skuid.model.getModel("Contact")
];
var messages = [];
$.each(models,function(i,model){
   $.each(model.registeredLists,function(j,list){
       var listMessages = list.validateRequiredFields();
       if(listMessages && listMessages.length) {
           $.each(listMessages,function(){
              messages.push(this); 
           });
       }
   });
});
// If we have warning messages, do NOT proceed
if (messages.length) {
    // Have our step's editor handle the messages
    stepEditor.handleMessages(messages);
// Stop the Action Sequence, and execute any on-error actions
    return false;
}
// Otherwise proceed!

(b) If you are doing a bunch of asynchronous operations within your Snippet, you can return a jQuery Deferred as part of a result object. If you call reject() on this Deferred, then the Action Sequence will be terminated and any on-error actions will be run. 

Example:

var params = arguments[0],   
    step = params.step,
    stepEditor = step.editor,
    $ = skuid.$,
    deferred = $.Deferred();

// Clear our list of messages
stepEditor.clearMessages();

var models = [skuid.model.getModel("Account"),skuid.model.getModel("Contact")];
var messages = [];
$.each(models,function(i,model){
   $.each(model.registeredLists,function(j,list){
       var listMessages = list.validateRequiredFields();
       if(listMessages && listMessages.length) {
           $.each(listMessages,function(){
              messages.push(this); 
           });
       }
   });
});

// If we have warning messages, do NOT proceed
if (messages.length) {
    // Have our step's editor handle the messages
    stepEditor.handleMessages(messages);
    deferred.reject({
         messages: messages,
         step: step,
         wizard: params.wizard
    });
} else {
     deferred.resolve({
         step: step,
         wizard: params.wizard   
    });
}
return { deferred: deferred };
(Edited)
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Zach - This is awesome, thank you for a great write-up and the team for delivering this functionality. Its going to make a world of difference in our development approach!
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Edit - I found it! Please ignore the below question. For others looking for this, when you choose a model action properties, on the action item itself there is an icon for adding on-error actions or deleting the action. See the attached screen-shot for reference and/or information regarding on-error is available in the newly updated tutorial at http://help.skuidify.com/m/components.... Thanks to the Skuid team for the continued doc updates! Sorry for the confusion on my part, it was staring me right in the face and I just kept overlooking it!

.

Zach -


Thanks again for the above, I've got it implemented using both approaches (return false & using deferred) and it's working just as you described.


Question - You mention above about "on-error actions" that are defined will be invoked when returning false or deferred.reject is called. I can't locate a way to define the "on error" actions in the actions list, etc. Can you shed some light on how to add these? In short, what I'm looking for is a set of actions to invoke only when the action sequence fails at some point.


Thanks!
(Edited)