Sunday, February 19, 2012

Namespaces in CRM JavaScript

As a consultant working with Dynamics CRM you should probably expect at some point to be working for a client whose CRM installation has been worked on by another consultant or that is using any number of different third party solutions. If a third party solution is referencing a large and/or minified JavaScript file you could accidently find yourself duplicating a method name and causing yourself a large amount of frustration trying to figure out why your JavaScript isn’t working as it should, or worse yet, trying to find out why theirs isn’t working.

Here is an example of a naming collision and unexpected results because both referenced JavaScript files contain the same method name of “Account_OnLoad”.

3rd Party JavaScript file – contains this code:
function Account_OnLoad() {
     Xrm.Page.getAttribute('telephone1').setValue('Not Mine');
}
My JavaScript file – contains this code:
function Account_OnLoad() {
     Xrm.Page.getAttribute('name').setValue('Mine');
}

Here are the properties of the form we are working on. It includes references to both of the files we are working with. We are expecting the Account name field to be populated from our JavaScript.

NamespacesJS1

So when we preview the form, we don’t see the results we are anticipating.

NamespacesJS2

So what went wrong? Despite the fact we are not calling the “Account_OnLoad” method in the 3rd Party JavaScript file from our CRM form properties, we are still loading both versions. When it comes time to actually make the method call, the instance that was load last is recognized and executed.

To prevent this problem in the future we can use a namespace in our JavaScript to help keep our code in its own context. It appears there are a few different techniques for doing this, but this one in particular is easy to use.

Lets change My JavaScript file to contain this code:
if (MyNamespace === undefined) {
    var MyNamespace = {};
}

MyNamespace.MyValue = 'Mine';

MyNamespace.Account_OnLoad = function () {
     Xrm.Page.getAttribute('name').setValue(MyNamespace.MyValue);
}

So what did we do here? We check to see if “MyNamespace” exists and if it doesn’t we create it. We also created a variable called “MyValue” in “MyNamespace” and assigned it a value. Then we assign the “Account_OnLoad” function to “MyNamespace”. In the future when we want to reference “MyValue” or “Account_OnLoad”, we need to preface them with “MyNamespace.”.

Make sure you publish the changes to the JavaScript file. Also make sure and change the name of the function being called in the Form – OnLoad to reference the new namespace.

NamespacesJS3

So now when we preview the form, we see this.

NamespacesJS4


Exactly what we expected to happen.