Customization of Associated Views in MS CRM

Associated views in Microsoft Dynamics CRM can be enhanced to provide relevant historical information about related entities.  By showing inactive records, and giving them a unique visual style, the data takes on new meaning.

Example Formatting of Inactive Records

Below, I have detailed the process followed to display inactive records, and then format the rows of the associated view (from within the parent entity’s OnLoad event).  Please look through what I have done, use it freely, and change it to your liking.

The solution that I have implemented involves attaching to a succession of functions on elements related to the associated view. WARNING! The suggestions that follow do not come with any warranty or guarantee of service, and are most likely not supported by Microsoft. Use at your own risk!

There are a number of ways to go about doing this, but here are two:

Enabling both active and inactive records, however, proves to be only the first step. An issue arose while doing a little usability testing that showed that simply having the status listed as one of the columns did not create enough differentiation between the records. Additionally, there were cases where the associated view’s toolbar needed to be stripped down to only one or two functions (to reduce visual clutter). Below is the end result of the manipulation of the associated view using only client-side Javascript:

There are two ways in which we display associated views. The first way is through the system-generated navigation on the left-side of any entity. These links add an iframe to the page whose source is the associated view. The second way is to put the associated view in an iframe directly on the tab(s) of the current entity:

This change allows the associated view to be visible in a more relevant context within an entity.

For the use of this article I will be using the system-generated navigation, and attaching Javascript events that help to give the associated view therein a more user-friendly appearance.

Step 1: Adjust the Associated View

Follow one of the methods above that allows inactive records to be visible. Adjust the Associated View to include the Status column (I put ours toward the end, since it will not be necessary to see it once the styling is done).

Step 2: Add the Javascript to Onload of the Parent Entity

Some of the values in the code below require you to find titles, or IDs of HTML elements. To accomplish this I recommend using Fiddler and your choice of text editor.

function setAssociatedOnClick() {
 
// Get the left-hand navigation links
navbar = document.getElementById("crmNavBar");
navlinks = navbar.getElementsByTagName("a");
 
for (var i = 0; i < navlinks.length; i++) {
 
// Use the tooltip text to find the correct navigation link
// Could obviously use your choice of options here
if (navlinks[i].getAttribute("title") == "TITLE OF ASSOCIATED ENTITY") { 
 
// Store the current onclick behavior
var currOnClick = navlinks[i].onclick;
 
// Override the current OnClick event, but start with the current one
// This prevents losing any CRM-customized JScript
navlinks[i].onclick = function() {
 
currOnClick();
iframes = document.getElementsByTagName("iframe");
 
for (var j = 0; j < iframes.length; j++) {
 
// Check that this frame is for our related entity
if (iframes[j].id.indexOf('ASSOCIATED ENTITY STRING') >= 0) {
 
// Change what happens when the associated view iframe loads
iframes[j].onreadystatechange = function() {
 
if (this.readyState == "complete") {
 
var grid = this.contentWindow.document.getElementById("divDataArea");
 
// Process the data grid when it loads/reloads/sorts/refreshes
grid.onpropertychange = function() {
 
// Get all the NOBR elements (where text is stored)
var btnlist = this.getElementsByTagName("nobr");
 
for (var i = 0; i < btnlist.length; i++) {
 
// Check if the text is 'Inactive' (needs some refinement)
if (btnlist[i].innerHTML.indexOf("Inactive") >= 0) {
 
// 'Inactive' row-level style formatting
btnRow = btnlist[i].parentNode.parentNode;
btnRow.style.color = "#909090";
 
// Deal with style changes for row sorting/clicking
btnRow.onpropertychange = function() {
	var collist = this.parentNode.parentNode.getElementsByTagName("col");
	var sortCol = 0;
	for (var m = 0; m < collist.length; m++) {
		 sortCol = (collist[m].className != null && collist[m].className.indexOf("SortedColumn") >= 0) ? m : sortCol;
	}
	if (this.className.indexOf("SelectedRow") >= 0) {
		this.style.backgroundColor = "#F0F0F0";
		this.style.color = "#333333";
		this.childNodes[sortCol].style.backgroundColor = "#F0F0F0";
		this.childNodes[sortCol].style.color = "#333333";
	}
	else {
		this.style.backgroundColor = "#FFFFFF";
		this.style.color = "#909090";
		this.childNodes[sortCol].style.backgroundColor = "#EAF3FF";
		this.childNodes[sortCol].style.color = "#909090";
	}
}}}}}}}}}}}}

Here are the basic ideas in the code:

  • When the content is loaded, find the link to the associated entity
  • Manipulate that link to do what it normally does on a click, and add some extra behavior after that
  • Attach a listener for when the associated view loads as well as when the grid changes
  • When the grid loads, step through the records and adjust them

Once you have access to the grid, the possibilities for manipulation are pretty much endless. We have even added functions in the grid’s controls to allow a return to the original sorting (by just refreshing the page), and options on the bar for external links. I hope this helps stir your imagination for the possibilities that are available. Please ask any questions you might have, and I will try to answer them to the best of my ability.

This entry was posted in Development. Bookmark the permalink.

3 Responses to Customization of Associated Views in MS CRM

  1. Bill Tetrault says:

    I think the function setAssociatedOnClick() would work for me, just not sure how to implement on some thing like
    if (document.getElementById(‘nav_mdv_campaign_campaignresponse_accepted’) != null) {
    document.getElementById(‘nav_mdv_campaign_campaignresponse_accepted’).onclick = function() {
    loadArea(‘areaCampaignResponses’);
    }
    }

    I see how I could modify function to hind records with a field set to ‘registered’ just need to get that recordset

  2. Dave Murdock says:

    Luke,

    Your solution interests me, as I need to accomplish a similar task. I’m a newb developer and I’m hoping you’d be willing to hold my hand a bit.
    I’ve already successfully moved the related records to an IFRAME. Would you perhaps add some detail to how i can adapt your code to work in conjunction with the associated records being in this IFRAME. Such as which ELEMENTS need to fit into which parts of your script.

    Thanks in Advance,
    Dave

  3. paolo titta says:

    thanks very nice idea and code

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">