-
Dynamics CRM 3.0 Client-side Programming: FireOnChange()
In the article, Including custom JavaScript files in MSCRM 3.0, I discussed using an external JavaScript code library to help reduce maintenace costs. Seemed like a good idea, at the time. Then I got to thinking about the CRM Laptop client and how it is disconnected from the main CRM server and realized that I had just created an unsupportable and unviable installation.
Shorely thereafter, Michaeljon Miller posted an article discussing the same situation: Using the CRM SDK offline
So I'm thinking I'm relatively screwed, uh, technically speaking, of course.
I was also starting work on a custom mortgage calculation entity that contained about 40 different formulas. And it got me to thinking about how, and more importantly, where, I was placing my JavaScript calculation code.
I was basically converting an Excel worksheet that had all of the calculations necessary to make the Mortgage Calculator function. The problem is, Excel allows you to reference cells from other cells and automagically perform calculations when any referenced cell changes value.
What I needed was a method for replicating that exact functionality. The only problem was knowing where to put the calculations. Ideally, I would put them behind the Field that contained the value I wanted to calculate. That would simplify the calculations by retaining them in a singular location that would automatically update itself. The only issue with that idea was the fact that most of these Fields were not meant to be edited. They would be read-only. Since the OnChange event doesn't fire unless you manually change and leave a Field, the calculation would never fire.
It was just then that I remembered seeing this really neat looking CRM 3.0 client-side function called FireOnChange().
What Does the FireOnChange() Do?
Well, it fires the Field's OnChange() event. Pretty cool huh?
Starting from Scratch
So let's rewrite the solution we created in our original article using supported and therefore supportable technologies. Here is our user interface:

and here is our JavaScript calculator:
crmForm.all.new_total.DataValue=
crmForm.all.new_price.DataValue*
crmForm.all.new_quantity.DataValueAgain, we can put the above code in the OnChange events of Price and Quantity, but that really doesn't help our goal of maintainability. So I'll tell you what, let's put that code only in the Total field's OnChange event. And before you start calling me eight kinds of idiot, let me finish.
In the OnChange event for both Price and Quantity, I want you to put the following code:
crmForm.all.new_total.FireOnChange();
Now, go Preview the form and enter amounts into Price and Quantity. It should have updated Total with the correct number.
Caveats
I only ran into one issue using FireOnChange(). You can't execute a second FireOnChange() event while an existing FireOnChange() event is executing. For example:
- I add a Grand Total Field to the form.
- At the bottom of the Total Field's OnChange() event, I add:
GrandTotal.FireOnChange(). - This means when Price executes Total.FireOnChange(), Total in turn executes GrandTotal.FireOnChange().
- This will result in something called a Stack Error.
My guess is that the Stack Error is caused by the FireOnChange() being called recursively and it wasn't built for that.
To make matters worse, the actual error specifies Line 0 as the location. I had 40+ separate calculations so it was of no help at all. It was only after a number of hours of manually tracing and debugging that I finally figured out what was happening.
Other Considerations
You may be wondering why I told you to put the FireOnChange() into both Price and Quantity fields and not just the Quantity field. That is because you can never count on a user doing the exact thing in the right order.
So, if you are thinking that users will always enter Price, then Quantity, you're setting yourself up for failure, since they could change their mind and change the Price for some reason. Without the total.FireOnChange() in Price's OnChange event, we would never pick up that change. That would result in a bad user experience and a support call.
In Summary
I can't stress enough how much proper planning will help you here. My biggest mistake was not knowing and understanding that I couldn't recursively call FireOnChange() and when I found out, I had already had all of my calculations in place which makes for a bunch of spaghetti-code.
So, figure out where you need your calculations, which ones can be stand-alone and which need to be executed remotely ( via FireOnChange() ). After that, it is simply a matter of defining the execution rules for the calculation and making sure that no one calculation calls FileOnChange() recursively.
Next Steps
I have it on my list to create an unsupported application that will read the Form from the database and extract the JavaScript code and stick it into a Word document for documentation purposes. I'll let everyone know when I'm done with that. I'll probably charge a gazillion dollars (US) for it too.
I can't get to Vegas on my looks, after all. :)
Customization, Dynamics CRM 8,700 views5 responses to “Dynamics CRM 3.0 Client-side Programming: FireOnChange()”
-
only issue with that idea was the fact that most of these Fields were not meant to be edited. They would be read-only.
I had a total, grand total and other fields where the value was worked out based on other fields (very similar to your design). I made the total and grand total read only using the disable option on the form designer. The values would be propergated using javascript and this worked fine.
Interesting the values of the field would be stored correctly in the database and so, on the creation of the item but if you tried changing them later on the values would not be updated in the database even though they were changing successfully with the javascript.
Appeared to me that disabled fields with values in them and null values in the database get written to the database while disabled fields with values in them with non-null values in the database do not get written.
-
mitch March 7th, 2006 at 15:37
Robert,
You are correct. Disabled fields do not get written back to the database.
Ryan Farley has a great article on Read Only and Disabled fields:
http://crmdeveloper.com/blog/archive/2006/03/06/17312.aspxCheck that out.
In addition, look at the CRM 3.0 SDK for the following command: .ForceSubmit
It is supposed to set a flag that will cause it be write back to the database regardless of state.
Mitch
-
Thanks for the information on ForceSubmit. I noticed in the SDK while looking at it that for disabled it states
The field is displayed as read only to the user; however it can be updated by a script. This field is submitted to the server when it is modified.
The second part about being submitted is definately not correct :(
-
edwardsdna February 28th, 2007 at 17:07
Hi,
I just used your .FireOnChange(); suggestion and it worked great! Thank you for the solution.
Donna
-
Hi All,
The CRM JavaScript FireOnChange() method does not fire when the Crm record is opened in ReadOnly or Disabled mode.
Further the FireOnChange() method will fire when changed to onchange0() in case of readonly mode or disabled mode .
This will also not work when the field on Crm Form is in locked mode
i.e. as an example the customer field on the Case Form.
For this field the FireOnChange() or onchange0() method will not get called when the record is opened as in readonly or disabled mode.I guess this is a bug with MS Crm 4.0..
Pls let me know if any one has some solutions or workaround for this one.
Thanks
Susan
Leave a reply




