Managing the Forms 2.0 API event stack, and something to look out for
In Forms 2.0, you can have multiple event listener functions for a single event. By calling form.onSubmit
or its peers with different functions in succession, you create an event stack.
Later, when the corresponding event fires, functions in the stack are executed from first added to last added. It's a great feature that works automatically.
But when you pass a falsy argument to onValidate
, onSubmit
, or onSuccess
(or pass no arg at all, like form.onSubmit()
, which will be treated like form.onSubmit(undefined)
) you will remove the entire existing event stack for that event type.
This remove-all behavior is not documented. And if you — or someone whose code you've copy-and-pasted — didn't know about it, your well-thought-out custom code can break.
Imagine one of your included JS <script>
s has a config block like this, where any of the event properties are optional:
var myLibraryConfig = {
events : {
submit : function(form){
// change or edit user-supplied values
// before the form is submitted
},
success : function(vals,tyURL){
// log something to an analytics service
// when the form is successfully posted
}
}
}
And then elsewhere in the code, it adds the event listeners like so:
MktoForms2.whenReady(function(form){
form.onValidate(myLibraryConfig.events.validate);
form.onSubmit(myLibraryConfig.events.submit);
form.onSuccess(myLibraryConfig.events.success);
});
Unfortunately, simply because myLibraryConfig.events.validate
was left off the config object, all other custom validation functions have been removed, since you've ended up running form.onValidate(undefined)
.
By leaving off validate
, you probably meant “don't do any special new validation, but don't touch validation code supplied in other scripts“ but you get way more than you bargained for.
It gets even more confusing if you have scripts loading asynchronously, because whether your validation will work depends on the (essentially random) script load order. If Script #1 loads first and runs form.onValidate(undefined)
, that still lets Script #2 add validation functions afterward. But if Script #2 loads first its validators will be removed by Script #1.
There isn't really a way to eliminate this issue (short of fully shadowing the on*
methods, which I won't recommend today). Instead, you must make sure that your code, and anybody else's you use on your site, is incapable of passing the argument undefined
, null
, or false
to one of the event adder functions. (Same goes for falsy ""
or 0
, but those are probably only going to happen if there are bigger bugs.)
If you want to remove all listeners, then deliberately passing no arguments (form.onSuccess()
) is acceptable and it's impossible for this to happen by accident.