tl;dr
Setting data validation error on the form level with Xrm.Page.ui.setFormNotification call will NOT stop form from closing, setting errors on individual controls with Xrm.Page.getControl(arg).setNotification, on the other hand, will. To achieve even better results, use business rule instead of the javascript.
Slightly longer version
Friend of mine pinged me to help with the script he cooked to verify the data. Script was hooked up to the form’s OnSave event and looked like the following:
function checkFlavour(context) { flavour = Xrm.Page.getAttribute('new_flavourid') .getValue(); if (flavour != null && flavour[0].name == 'Chocolate') { Xrm.Page.ui.setFormNotification( 'We are OUT of Chocolate!','ERROR','choco'); context.getEventArgs().preventDefault(); } else { Xrm.Page.ui.clearFormNotification('choco'); } }
The complaint was that script was not working when user was pressing SAVE & CLOSE button. In the end of the day I was unable to reproduce the problem as preventDefault() call was doing it’s job on my machine. However, I found that my friend, as some other developers before him, was under the impression that setFormNotification alone was supposed to do the job.
The reality is that this function displays an error message on the form level but does nothing to stop the form from closing. Setting notification on individual controls with setNotification call, on the other hand, will block the form from saving and closing.
Instead of “fixing” the script, friend of mine opted for a business rule that worked like a charm:
The added benefit, of course, is the server-side execution of the business rules. If a sneaky user tries to bypassing the scripts by importing a record with forbidden flavor:
Name, Flavour "Nom nom", "Chocolate" "Meh", "Strawberry"
They still will be stopped in their tracks if scope of the business rule is set to Entity: