Using jQuery in MS Dynamics CRM

By Haan on Wednesday 2 June 2010 16:09 - Comments (8)
Category: Dynamics CRM, Views: 10.079

Introduction
In this blog post, I'll share some experiences that I recently had with using jQuery script in MS Dynamics CRM 4.0 forms. For those not familiar with MS Dynamics CRM and / or customizing forms, this blog post will not be very interesting.

A little introduction first. I was asked if it would be possible to re-arrange fields on a CRM form. More specifically, re-arrange address fields to reflect the address layout of the country that is selected. I knew that a former collegue had tried to do the same, but couldn't get it working, but that was before jQuery was available ;)

After writing this blog post, I realize it has gotten rather large and still misses some detailed background information. I may split this post into separate parts in the future.
Getting started
After delivering a little Proof of Concept page, I started developing the javascript. In this blog I'll explain about the process, hopefully it helps and / or inspires others (and maybe I'll get some feedback about how to do things better too ;) )

The first thing that we need to do, is to inject a script reference to the jQuery script into the form's <header> tag. I used the method explained in this blogpost for that. There are other ways, for example load the script with the Eval() function as explained here, but I think injecting a script tag is cleaner (Eval() is Evil after all ;) )

After this we're ready to go!
The environment
In my specific case, I used the customeraddress entity. On the form is a dropdown list with countries. When a country is selected, the layout (5 possibilites) is determined in the script.
To be able to set different layouts, I created a 5 x 3 grid, with a number of 'whitespace' fields, that can be used to create empty spaces and are hidden with a line of jQuery script. Within this grid the fields can be set to any location. Let me show the end result first:

This the form when it opens to create a new record:
http://tweakers.net/ext/f/JWn5mIpHaBY9on76YSa1xnh5/full.png

See how the layout has changed to reflect the selected country:
http://tweakers.net/ext/f/5tPW5vSIjWg1Xuh8m1BQr78o/full.png
Show me the magic!
Now the interesting part, the actual scripts!

First to be able to determine where each field needs to be set, I defined a two-dimensional array for each layout:

JavaScript:
1
2
3
4
5
6
7
// define different formats as multi-dimensional arrays representing the layout on the form
layout1 = new Array(new Array(streetname, buildingNumber, numberSuffix),
                    new Array(line1, whitespace3, whitespace4),
                    new Array(line2, whitespace5, whitespace6),
                    new Array(postalcode, city, stateOrProvince),
                    new Array(whitespace7, whitespace8, whitespace9),
                    new Array(whitespace10, whitespace11, whitespace12));



Notice that I use Visual Studio to be able to have IntelliSense support for javascript in general and jQuery in specific.

The function for hiding the whitespaces is as follows:

JavaScript:
1
2
3
4
HideWhiteSpaces = function ()
{    
    $("td[id*='whitespace']").hide();
}



Thusfar things are not too complicated. But now we're ready to shuffle the fields on the form to reach to desired layout. An important thing to notice is that is not possible to just remove the fields and then place them back in the right order, because this breaks some CRM scripts that are attached to all fields on CRM forms. This means that we have to switch fields until we have the desired layout. Special care is needed when fields moved to another row, because you need to leave at least one field on a row, or else you will have no reference to that row anymore.

Another important thing to know, is how a CRM form is built. Let me show how this looks in the IE Developer tool:
http://tweakers.net/ext/f/Guvrg4xqOvQeYIRv2yXqhi5x/full.png

As you can see, each line is a table row, and each label / input field element is wrapped in a <td> element.

So to be able to move a field, we have to get a jQuery reference first, and then move both the input and the label elements.

JavaScript:
1
2
3
4
5
6
7
GetjQueryParentContainer = function (fieldName)
{
    return $("input[id=" + fieldName + "]").parent();
}

var line1Field = GetjQueryParentContainer("line1");
var line1Label = line1Field.prev();



Moving field "line2" before "line1" can now be done as follows:

JavaScript:
1
2
3
4
5
// here we use the insertBefore() function, 
// in other cases you may want to use insertAfter()
// for many cases, both are possible to achieve the same result
line2Field.insertBefore(line1Label);
line2Label.insertBefore(line2Field);



Well that's pretty much it, everything else is just repeating and combining the steps above, until the new layout is set.

In my current script all layouts are achieved through hard-coded steps, because it turned out to be very difficult to do it automatically, especially when you have to deal with fields that are moved to another row. I hope to fix that in the future.

update
I forgot an important script that fixes the tab index after a layout has changed:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
SetTabIndex = function ()
{
    var tabindex = 1;
    $('input').each(function ()
    {
        if (this.type != "hidden")
        {
            $(this).attr("tabindex", tabindex);
            tabindex++;
        }
    });
}

Volgende: Using the log4net AdoNetAppender to log to a bit(boolean) column 06-'10 Using the log4net AdoNetAppender to log to a bit(boolean) column

Comments



By Tweakers user TerraGuy, Wednesday 2 June 2010 22:55

Yes, thanks for showing this neat piece of work!

By Tweakers user wheez50, Wednesday 2 June 2010 23:28

Shouldn't even be remotely interested to me at all. But I did wonder, I hope you encoded countrydependance per country in the page somewhere? Because if you'd have to (ajax-) fetch it still, you'd get people like me annoyed. I always end up filling in an address field that gets rearranged later on... You know, after selecting country, I'll focus on keyboard while tabbing and start typing, then back to the screen to see the screen changing and with it half my new input.

By Tweakers user Haan, Thursday 3 June 2010 08:25

wheez50 wrote on Wednesday 02 June 2010 @ 23:28:
Shouldn't even be remotely interested to me at all. But I did wonder, I hope you encoded countrydependance per country in the page somewhere? Because if you'd have to (ajax-) fetch it still, you'd get people like me annoyed. I always end up filling in an address field that gets rearranged later on... You know, after selecting country, I'll focus on keyboard while tabbing and start typing, then back to the screen to see the screen changing and with it half my new input.
You don't have to worry about that, the layout changes instantly when a new country is selected. And indeed the type of layout for each country is stored on the page, so no additional fetch is required.

By Tweakers user crisp, Thursday 3 June 2010 08:57

but that was before jQuery was available
I wonder why your collegue wasn't able to do this, or why you think that jQuery makes this any easier to accomplish. What I see are a couple of lines of jQuery that can easily be replaced by roughly the same number of lines of plain javascript using some DOM methods ;)

By Tweakers user Haan, Thursday 3 June 2010 12:47

crisp wrote on Thursday 03 June 2010 @ 08:57:
[...]

I wonder why your collegue wasn't able to do this, or why you think that jQuery makes this any easier to accomplish. What I see are a couple of lines of jQuery that can easily be replaced by roughly the same number of lines of plain javascript using some DOM methods ;)
I know you're not a fan of jQuery ;) But for me it makes life easier. And as I mentioned at the beginning, this blog will only be really interesting for those who work with Dynamics CRM. Let's just say that it contains a lot of proprietary code and script that you have to deal with and jQuery helps to make it a bit easier.

By Tweakers user FlowinG, Thursday 3 June 2010 13:56

MSCRM is either way no heaven when it comes to scripting. You often face the problem of have to inject custom scripts or have to heavily modify the dom-structure. Fortunately it's easier to add and reuse scripts in the upcoming release of CRM 5. This versions provides an option to centralize the management of scripts.

Besides that, I agree with crisp. There is no need for using JQuery and loading a giant library while using just a tiny part of it.

By Simon Jackson, Tuesday 15 June 2010 22:12

Nice work thanks, should I get this requirement, I'll be sure to start here.

Thanks for sharing,

Cheers
Si

Comments are closed