Saturday, August 2, 2014

Display Custom Fetch in Grid

I wrote this a few years back. It enables you to display a custom FetchXml query inside a CRM grid.
I made a few modifications to support 2011 , IE and chrome.

Note: This version requires jquery and XrmForm as web resources.
If you don’t want to use the entire XrmForm object (see here) you can replace the function calls to XrmForm with original CRM SDK functions.

Here are the XrmForm methods being utilized in FetchViewer.
For an updated XrmForm click here

//companyname_SDK.js
function XrmForm() {
    //this is a partial implementation of XrmForm
    var userAgent = window.navigator.userAgent;
    xfrm.IsIE = userAgent.indexOf("MSIE") != -1;
    xfrm.IsChrome = userAgent.indexOf("Chrome") != -1;
    
    xfrm.GetCrmUrl =
    xfrm.GetClientUrl = 
    xfrm.GetServerUrl = function() {
        return context.getClientUrl 
            ? context.getClientUrl()+ "/" 
            : context.getServerUrl();
    }
    xfrm.GetHost = function () {
        return location.protocol + "//" + location.host + "/";
    }

}

function FetchViewer(iframeId) {
    var fev = this;
    var vform, m_iframeTab, m_iframeDoc;
    var fetchDataUrl = xrmForm.GetCrmUrl() + 
                        "AdvancedFind/fetchData.aspx";

    fev.Entity = "";
    fev.Iframe = null;
    fev.FetchXml = "";
    fev.QueryId = "";
    fev.LayoutXml = "";

    fev.RegisterOnTab = function(tabIndex) {
        fev.Iframe = document.getElementById(iframeId);

        if (!fev.Iframe)
            return alert("Iframe " + iframeId + " is undefined");

        m_iframeDoc = getIframeDocument();
        m_iframeDoc.body.innerHTML = [
          "<table height='100%' width='100%' style='cursor:wait'>",
            "<tr>", 
              "<td valign='middle' align='center'>", 
                "<img alt='' src='", xrmForm.GetHost(), 
                          "/_imgs/processing_loader.gif'/>", 
                "<b>Loading View...</b>", 
              "</td>", 
            "</tr>",
           "</table>"
        ].join("");

        parseInt("0" + tabIndex) == 0 
           ? fev.Refresh() 
           : $(fev.Iframe).bind("load", RefreshOnReadyStateChange);
    }

    function RefreshOnReadyStateChange() {
        if (fev.Iframe.contentWindow.document.readyState != 'complete')
            return;
        fev.Refresh();
    }

    fev.Refresh = function() {

        if (!fev.Iframe)
            return alert("Iframe " + iframeId + " is undefined");

        m_iframeDoc = getIframeDocument();
        $(fev.Iframe).unbind("load", RefreshOnReadyStateChange);

        xrmForm.IsIE ? createIEForm() : createChromeForm();
        $(fev.Iframe).bind("load", OnViewReady);
    }

    function createIEForm() {
        var create = m_iframeDoc.createElement;
        var append1 = m_iframeDoc.appendChild;
        vform = create("<FORM name='vform' method='post'>");

        var append2 = vform.appendChild;
        append2(create("<INPUT type='hidden' name='FetchXml'>"));
        append2(create("<INPUT type='hidden' name='LayoutXml'>"));
        append2(create("<INPUT type='hidden' name='EntityName'>"));
        append2(create("<INPUT type='hidden' name='DefaultAdvFindViewId'>"));
        append2(create("<INPUT type='hidden' name='ViewType'>"));
        append1(vform);

        vform.action = fetchDataUrl;
        vform.FetchXml.value = fev.FetchXml;
        vform.LayoutXml.value = fev.LayoutXml;
        vform.EntityName.value = fev.Entity;
        vform.DefaultAdvFindViewId.value = fev.QueryId;
        vform.ViewType.value = 1039;
        vform.submit();
    }

    function createChromeForm() {
        vform = $("<FORM name='vform' id='vform' method='post'>");
        $(vform).append($("<INPUT type='hidden' name='FetchXml'>"));
        $(vform).append($("<INPUT type='hidden' name='LayoutXml'>"));
        $(vform).append($("<INPUT type='hidden' name='EntityName'>"));
        $(vform).append($("<INPUT type='hidden' name='DefaultAdvFindViewId'>"));
        $(vform).append($("<INPUT type='hidden' name='ViewType'>"));
        $(m_iframeDoc.body).append(vform);

        vform = $('#vform', m_iframeDoc.body)[0];
        vform.action = fetchDataUrl;
        vform.FetchXml.value = fev.FetchXml;
        vform.LayoutXml.value = fev.LayoutXml;
        vform.EntityName.value = fev.Entity;
        vform.DefaultAdvFindViewId.value = fev.QueryId;
        vform.ViewType.value = 1039;
        vform.submit();
    }

    function OnViewReady() {
        if (fev.Iframe.contentWindow.document.readyState != 'complete')
            return;

        fev.Iframe.style.border = 0;
        $(fev.Iframe).unbind("load", OnViewReady);
        m_iframeDoc = getIframeDocument();
        m_iframeDoc.body.scroll = "no";
        m_iframeDoc.body.style.padding = "0px";
    }

    function getIframeDocument() {
        return fev.Iframe.contentWindow.document;
    }
}

var xrmForm = new XrmForm();

The actual values of FetchXml , LayoutXml, EntityName and QueryId can be extracted using advanced find:
1.The FetchXml can be downloaded easily using advanced find toolbar button.
2.Other values need to be extracted using the following instructions:
    a.Open Advance find in chrome.
    b.Build your FetchXml query, add desired columns and run it once.
    c.Go back to the query designer and Press F12 to open chrome dev tools
    d.Press Esc to open the console if it’s not yet opened.
    e.Enter the following lines and press enter:
      i.For LayoutXml – document.all.LayoutXml.value
      ii.For EntityName – document.all.EntityName.value
      iii.For QueryId – document.all. DefaultAdvancedFindViewId
f.You can also extract FetchXml using this line:
    i.document.all.FetchXml.value
    g.Paste values in your code (see usage example)

Usage example:
fAccounts = new FetchViewer("IFRAME_accounts");
   fAccounts.FetchXml  = "Paste FetchXml  here";
   fAccounts.LayoutXml = "Paste LayoutXml here";
   fAccounts.Entity    = "account";
   fAccounts.QueryId   = "{00000000-0000-0000-00AA-000010001001}";
   fAccounts.RegisterOnTab(0); //IFRAME ON THE DEFAULT TAB



3 comments:

  1. I have used this code, works fine in CRM 2011, but It breaks the Command bar in CRM 2013

    ReplyDelete
    Replies
    1. We are also facing the same issue. did you get any solution to fix the command bar ?

      Delete
  2. I read your post and i really like your post.Thank you for sharing this post.
    MRL Promotions
    Custom Back Bar Displays


    ReplyDelete