We recently had a requirement at a client to put icons on sub-grids in Microsoft CRM 2013. I was able to accomplish this (in an obviously unsupported fashion) by using a few jQuery events.
First, I needed to figure out how the grids were being loaded. As it turns out, in Microsoft CRM 2013, the grids are no longer IFrames, but are now dynamically populated as HTML div’s, using jQuery. After realizing this, I was able to leverage an event called ‘DOMNodeInserted’.
The first step I took was to write a function to bind to this event using jQuery (http://api.jquery.com/bind/).
Here’s what I started with:
Once I had this in place, I knew I was going to want to make the function a bit more dynamic, so I made use of the eventData optional parameter. This would allow me to append items to “e.data”
I’ll get into exactly what ‘myObject’ is later on, but essentially it’s an object, and I’m passing in values:
Once this is set up, I need to make sure that the sub-grid I’m looking for exists. Once I do this, I can call my function to replace my text with icons.
Luckily for us, all the grids in CRM have an attribute ologicalname, which contains the logical name of the entity. This is pretty nice. If jQuery can find this element (length greater than 0), then we know it has been inserted in the page and we can call our function. Note that in my query, ive added “e.data.entityName”. This is taking the value that I passed into myObject (gbs_errorandwarning).
We notice when I built ‘myObject’, I included a ‘matchFunction’ with a name “errorAndWarning”. This is the name of the function I want to call once my table has been found on the page. Since I’ve passed this in as a variable, I can call the function using e.data.matchFunction, and pass in any parameters I need. I’m going to pass in my event object (e).
Once this was written, I decided to wrap my bind function into its own function, which I have in its own web resource (putting it into its own resource is optional, but made sense since we were going to leverage this in other places. I have to also allow my function to accept ‘myObject’ so that I can declare that elsewhere.
Now that we have that built, I need my match function.
The function first searches my table headings to see what column number the field I’m looking to replace. This will allow us to move the column around in the view layouts and still work for us.
The snippet to check for that is:
We need to subtract 1 at the end because the index starts at 0, but when we use jQuery’s “:nth” selector, that starts at 1.
Now let’s grab the table, find all the rows in it, and iterate over it so we can interact with them:
So now that we’re looping through our rows and column, we can do our manipulation. Within each iteration of our loop, we can use $(this) to reference the item we’re on, and avoid attempting to use the index. I also wanted to keep with the MSCM theme, so using IE’s developer tools, I was able to find out that the error and warning icons were simply just empty div’s of a certain class, so that made life easier.
Errors are : <div class= ‘ms-crm-ImageStrip-inlineedit_warning’></div>
And warnings are: <div class= ‘ms-crm-ImageStrip-notif_icn_warn16’></div>
Now that we know that, I can just check the text of the cell I’m looking at, and if it matches what I want, I can replace it using jQuery’s .html() function.
I need to make sure the event arguments are passed through so that I can access the data elements.
Now that my bind is hooked up in my bindobjects.js resource and the errorAndWarning in my page JS, all I have to do is call my bind function from my form OnLoad event and pass in the object which includes my entity name, field name, and the function I want to run to execute the code.
So what does this all look like when we put it together?
Here’s a snap of the original grid, without my code in place:
And now with:
Because the events are now bound to the grid, this gives us a few great side effects. Any time the grid refreshes, the icons will still be there. This includes when we delete records, and when we add new records, even if the record is added via a pop out window!
Since we’re just setting HTML, we can easily swap out the icons that I’ve used here with any web resource image we want.
In addition to being able to add in the icons, we can now use this bind event to know when the grid had been refreshed (ex when someone creates a new associated record). This could allow us to recalculate any fields that are dependent on children records.
If you’re using CRM as a platform for deploying line of business applications, make sure you’re getting the most from your investment by reading CRM Governance: What It Is, What It Isn’t, and How to Do It Right, an informative eBook written by governance experts.