An odd bug in a client's pre-existing codebase popped up recently where we found that the same event handler was firing twice occasionally. An easy to digest scenario to replicate this would be if every time the phone number field changed, a field containing a phone number revision count was incremented by one. What would happen in this scenario is that after a record had been created, if you then changed the phone number field, the revision field would increment by two instead of one.
What was the underlying issue? The event handler was firing twice because it was actually being attached twice, as the handler was being attached to the field in question through code, in the form load event handler.
You see, the form load event can indeed fire multiple times in the lifecycle of a form, but only twice at a maximum, and only in one situation. When you open a create form, the form load event fires. Then, when you save the record and it switches to an update form, the form load event fires again. This is the only time this happens. Therefore, if you were to open an existing record, this issue would not be reproducible.
What all of this means is that you can't count on the form load event to fire only once, but you also can't lean on it to fire every time the user saves. We therefore must account for this inconsistency and leverage other methodologies if we need to do something every time the user saves.
Don't worry young Padawan, we can fix this!
You bet Ani! Just keep reading...
I will teach you everything I know, and you will become a far greater developer than I could ever hope to be...
So how do we solve this conundrum?
One possible solution you might think would to use the event registration dialog in the form customizations. In other words, use the Dynamics UI to register the events. While this is not an altogether horrible idea, we would not recommend this approach. Why is that, you ask? There are many benefits to registering your events in code, such as:
- You can see all of your events that are registered on that form, all in one place (you don't need to go to the Dynamics environment to see what's attached to what).
- You can leverage source control to more easily see how event registrations changed over the lifespan of the codebase.
- Registering your events in code should feel natural, when developing using JavaScript outside of Dynamics, we attach our events in code. We almost never attach them in the presentation (HTML) layer. Consistency, woo!
Given all of those benefits, we need to look for another approach. Good thing there is another! Let's instead use a variable to track when the events have been attached. So, the process would be to check a variable like isFormLoaded
before attaching events, and if it's false
, go ahead and attach your events but then be sure to set isFormLoaded = true
when you're done.
Yep, it's that simple. Just remember to scope your variables appropriately so as to not leak that new isFormLoaded
variable of yours to the global scope so that we can dodge another potential bug!
Take this information and use it wisely, young Padawan. With this knowledge, prevent many bugs, we shall.