Posts
389
Comments
117
Trackbacks
40
September 2008 Entries
Interacting with parent controls in Microsoft Dynamics CRM 4.0.

If you do a search in Google on the title above, you'll find plenty of code samples of the javascript to get and set the values of controls on CRM 4.0 forms and even how to do it from an IFRAME in a page. As you may know if you have any experience of extending MS CRM 4.0, the IFRAME is a big part of offering extra functionality to users.

Of course, as you may know if you have a bit of a history in Web UI design, there are a few hurdles to be able to be allowed to run javascript if your IFRAME contains a page from a site that is different to the HTML page hosting the IFRAME. This so-called cross site scripting was a big problem in earlier browsers and security blocks added in to stop this being hijacked for nefarious purposes. To deal with this the form designer in CRM 4.0 has the option to switch this security on or off. Unfortunately this has its limitations and I found that the option did not have any effect on the script I was trying to run from the page in the IFRAME. In the end I had to create a virtual directory in IIS in the same website as CRM. The other part I had to watch for is that I used the URL from the root of the site, not the redirected path that the CRM application uses.

Once over that hurdle, I had a bit of a wrestle with Javascript and dragging it out of my brain at the same time! To explain what I was trying to do, I had two controls on the parent form to populate. No problem, I had the names of the attributes and CRM 4.0 has a nice way of naming fields and controls from the attribute names. Unfortunately I got an access denied error thrown by the script engine in the browser. By a process of trial and error I established that one control worked and the other did not. Not because of value types or anything, it was because one was a lookup and the other was a straight text field. Lookups need a different approach to accessing them, as they use an array as part of the matching to list setup.

Having established this, I dived in to the code in the Microsoft Dynamics CRM 4.0 SDK which is something like thus :

//Create an array to set as the DataValue for the lookup control.
var lookupData = new Array();
//Create an Object add to the array.
   var lookupItem= new Object();
//Set the id, typename, and name properties to the object.
   lookupItem.id = '{1AAC1363-01A1-DB11-8432-0003FF9CE217}';
   lookupItem.typename = 'account';
   lookupItem.name = 'A Bike Store';
// Add the object to the array.
   lookupData[0] = lookupItem;
// Set the value of the lookup field to the value of the array.
   crmForm.all.parentaccountid.DataValue = lookupData;

Fine, but what guid id is that and how was I going to find it out. Further searching established that it is the guid of the entity that is listed by the lookup. Finding this out was a bit of a hunt again. Firstly I found the name of the entity being looked up by checking the properties of the lookup on the parent form. This pointed me to the source entity. Then I navigated through settings to call up the entity. Doing this lined up a URL with the GUID on it - perfect. The typename was also shown on one of these property pages. I filled them all in, and it didn't work. I did some cursing of Javascript and started hunting again.

I finally ended up wandering the directories of the SDK again. If you browse down the folders client\howto\usinglookups there are two script files readvaluelookupcontrol.js and setvaluelookupcontrol.js. I opened up the latter and it has the following code:

// Create a lookupItem to store the values that you want to set to a target lookup control.
var lookupItem = new Array();

// Specify the values on the signature of LookupControlItem. These values are the GUID of pricelevel, the type code of pricelevel, and the name of the lookup value.
lookupItem[0] = new LookupControlItem ("{F31BB38A-0EC0-403F-99A6-3AF469D7D76E"}, 1022, "Retail");

// Set the form control value to the lookupItem that you just created.
crmForm.all.pricelevelid.DataValue = lookupItem ;

Ok fine, but the realisation dawned slowly that the second line of code was calling a function I hadn't seen so far. I was correct, after doing some more Google work to establish this. Further hunting revealed that this is a function used by the CRM application itself. If you go hunting in Inetpub, you will find the file that defines the function. Take a look at the file Lookup.js which you will find under the web root in _static\_controls\lookup . In there is the definition of LookupControlItem thus:

function LookupControlItem(sId, iType, sName, sOnclick, sDisplayClass, sData, sTypeName, iCategory, sAmbiguousRecordsXml)
{
this.id = sId;
this.type = iType;
this.name = sName;
this.onclick = sOnclick;
this.displayClass = sDisplayClass;
this.data = sData;
this.typename = sTypeName;
this.category = iCategory;
this.ambiguousRecordsXml = sAmbiguousRecordsXml;
}

Include the code by reference or placement, and call it in the style above and it will work.

Its up to you whether you wrap your parent call in a test (helpful for form load timing issues) but I found this worked in the end.

So the SDK is ok, but needs a bit of background knowledge to work with. Another really helpful file that comes with the SDK is a pdf of the Microsoft Dynamics CRM 4.0 UI Style Guide. Essential to match your UI to the rest of the CRM look and feel to make your IFRAME disappear - if you can work CSS and Style of course!

Thanks to Richard at Evorio for CRM support.

posted @ Tuesday, September 2, 2008 2:49 PM | Feedback (0)