July 16, 2013

How to bind a function to the Sub-Grid refresh event

A common customization requested by customers is to execute some logic when a Sub-Grid is refreshed. Unfortunately the Xrm Object Model doesn't provide a method to bind a function to the refresh event.
To implement this functionality is necessary to use unsupported JavaScript code, paying attention when a new rollup is released.
The following code is compatible with UR12/Polaris update that introduced cross-browser support for CRM 2011.
function AddEventToGridRefresh(gridName, functionToCall) {
   // retrieve the subgrid
   var grid = document.getElementById(gridName);
   // if the subgrid still not available we try again after 1 second
   if (grid == null) {
       setTimeout(function () {AddEventToGridRefresh(gridName, functionToCall);}, 1000);
   // add the function to the onRefresh event
Is possible to use the AddEventToGridRefresh function in two different ways. Assuming to attach the following function:
// function used in this example
function AdviseUser() {
   alert("Sub-Grid refreshed");
The function can be called directly passing the parameters inside the dialog box

or inside another JavaScript function:
function OnLoad() {
   AddEventToGridRefresh('accountContactsGrid', AdviseUser);
The first parameter is a string and quotation marks are necessary, the second parameter is the name of the function and must be written without quotation marks.

July 9, 2013

Set Account's Primary Contact as Recipient when creating a new Phone Call

When a new Phone Call is created starting from an Account, the default recipient is the Account itself.
If we want to set the Primary Contact of the Account as Recipient, we need to call the following function inside the OnLoad event of the Phone Call entity.
function ChangePhoneCallRecipientFromAccountToPrimaryContact() {
    // check if is a new phone call
    if (Xrm.Page.ui.getFormType() == 1) {
        // get the Phone Call To Recipient
        var to = Xrm.Page.getAttribute("to").getValue();
        // if the Recipient is an account we continue
        if (to != null && to[0].entityType == "account") {
            // get the account Id
            var accountId = to[0].id;    
            // get the right url for the OData Query
            var serverUrl;
            if (Xrm.Page.context.getClientUrl !== undefined) {
                serverUrl = Xrm.Page.context.getClientUrl();
            } else {
                serverUrl = Xrm.Page.context.getServerUrl();
            // build the request
            var ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc"; 
            var accountRequest = new XMLHttpRequest();
            accountRequest.open("GET", ODataPath + "/AccountSet(guid'" + accountId + "')", false); 
            accountRequest.setRequestHeader("Accept", "application/json"); 
            accountRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            // execute the request
            if (accountRequest.status === 200) {
                var retrievedAccount = JSON.parse(accountRequest.responseText).d;
                // retrieve the primary contact of the account
                var primaryContact = retrievedAccount.PrimaryContactId;
                // if there is a primary contact we set as new To Recipient
                if (primaryContact.Id != null) {
                    var newTo = new Array();
                    newTo[0] = new Object();
                    newTo[0].id = primaryContact.Id;
                    newTo[0].name = primaryContact.Name;
                    newTo[0].entityType = primaryContact.LogicalName;
            else {