Accessing Subgrid Data using Javascript in CRM 2013 and Earlier

Isaac Stephens, 24 January 2016

Magnetism has already published one blog post about accessing subgrid data through Javascript (which you can find here), but the methods used are only available in Dynamics CRM 2015. I recently needed to perform conditional logic on a form based on data in a subgrid within CRM 2013, so I couldn't make use of those methods and had to find another way.

My scenario: the client wants a field on a form to be marked as Business Required only if a specific record is associated by an N:N relationship within a subgrid. Subgrid data loads asynchronously so you need to wait for the subgrid to be ready, then you need to access the subgrid data and perform your business logic. The code below should hopefully be generic enough to reuse in a variety of similar scenarios.

// Form load function

onLoad = function () {

bindSubgridFunction();

performSubgridLogic();

}

 

// Function to bind performSubgridLogic() to the 'onrefresh' trigger of the subgrid. The 'onrefresh' trigger is called whenever a change is made to the subgrid or the user forces a refresh. This ensures that changes made to the subgrid are processed after the form has loaded

bindSubgridFunction = function () {

// Get the subgrid DOM element

var subgrid = document.getElementById("subgridname");

 

// Check whether the subgrid has loaded yet and bind the performSubgridLogic function to the 'onrefresh' trigger if so. If not, wait 2 seconds and try again

if (subgrid) {

subgrid.control.add_onRefresh(performSubgridLogic);

} else {

setTimeout(bindSubgridFunction, 2000);

}

}

 

// Function to access the subgrid data, when it's loaded and ready

performSubgridLogic() = function () {

// Get the subgrid DOM element

var subgrid = document.getElementById("subgridname");

 

// Check whether the subgrid has loaded yet and perform your processing logic if so. If not, wait 2 seconds and try again

if (subgrid) {

// Get the contents of the subgrid

var subgridContents = subgrid.control.GetRecordsFromInnerGrid();

if (subgridContents != null && subgridContents.length > 0) {

// Loop through each element in the subgrid and perform your logic

for (var i = 0; i < subgridContents.length; i++) {

// In this example, I check whether the name of the element matches a certain string and make a field on the form Business Required if it does

var elementName = subgridContents[i][3].innerText.toLowerCase();

if (elementName.localeCompare("match string") == 0) {

Xrm.Page.getAttribute("fieldtochange").setRequiredLevel("required");

return;

}

Xrm.Page.getAttribute("fieldtochange").setRequiredLevel("none");

}

}

// If we couldn't get the element, try again every 2 seconds

} else {

setTimeout(performSubgridLogic, 2000);

}

}

 

If you put this code in a Javascript web resource and bind the onLoad function to the form's onLoad trigger, your processing logic will trigger any time the form is loaded or changes are made to the subgrid.

Please note that this code is unsupported since the DOM is being accessed directly. However, as there's no supported way to access subgrid data in CRM 2013, you might want to make the concession of using unsupported code if you require this functionality.