08 July 2011

CRM 2011 Change SubGrid FetchXML - Updated for rollup 5

Subgrids are new feature to CRM 2011 and allow records that are linked to a record to be shown on the form. By default the linking is limited to records which are related to parent.

I had a requirement to show a list of leads which have the same company name as the current lead. A subgrid seemed to be the way forwards, in CRM 4.0 I'd have added an IFrame displaying an advanced find list, but the limitation of only displaying related records added something of a stumbling block.

With a bit of, unsupported, scripting I managed to work around this issue. Here's how:

1. Add a subgrid to the Lead form showing all leads. Take a note of the subgrid name.

2. Generate the FetchXML that you want to inject into the subgrid (Advanced Find is your friend here).

3. The following JScript method demonstrates changing the FetchXml for a subgrid called "RelatedLeads"


function UpdateSubGrid()
{
var leadGrid = document.getElementById("RelatedLeads");

//If this method is called from the form OnLoad, make sure that the grid is loaded before proceeding //Included extra null check as a rollup 5 fix
if (leadGrid ==null || leadGrid.readyState != "complete")
{
//The subgrid hasn't loaded, wait 1 second and then try again
setTimeout('UpdateLeadSubGrid()', 1000);
return;
}

//Update the fetchXML that will be used by the grid.
var fetchXml = "";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += " ";
fetchXml += "
";
fetchXml += "
";
fetchXml += "
";

//Inject the new fetchXml
leadGrid.control.setParameter("fetchXml", fetchXml);
//Force the subgrid to refresh
leadGrid.control.refresh();
}


4. As a minimum the method can be called from the OnLoad event but it's probably best to call it from the OnChange event of any attributes that are used to generate the FetchXML

26 comments:

  1. Thanks! This is just what I need!
    I do have a weird problem though. I am using CRM 2011 Online and the code breaks down at the "document.getElementById" statement... It can't find the ID... Perhaps you can help me out.

    The name of my grid is "mygrid", I am sure of this. But when I check ALL the ID names that look like "mygrid" that are on the form, using Javascript code, I get the following:
    mygrid_d,
    mygrid_c,
    mygrid_span,
    mygrid_visualizationCompositeControl,
    mygrid_compositeControl,
    mygrid_crmGridStrip,
    mygrid_gridStripDiv,
    mygrid_GridStripLabelMessage,
    mygrid_crmGridTD,
    mygrid_splitTD,
    mygrid_splitterImage,
    mygrid_paneTD,
    mygrid_pane,
    mygrid_paneControl,
    mygrid_crmVisualizationPaneStrip,
    mygrid_paneStripDiv,
    mygrid_VisualizationPaneStripLabelMessage

    A whole list of "mygrid" but not any that is exactly "mygrid". I can get any other field using the getElementById though...

    Now what did work for me was to use the following statement to get to the grid:
    var leadGrid = Xrm.Page.ui.controls.get("mygrid");

    But then the "setParameter", "refresh" and "readyState" commands don't work...

    Any ideas?
    Many thanks,
    Chris

    ReplyDelete
    Replies
    1. Did you get any solution for this ? I am experiencing same problem.

      Delete
  2. I am having a similar issue. The code above doesnt work for me either, even for CRM 2011 on-prem. Has there been any updates to the code or even CRM that is preventing this from working?

    ReplyDelete
  3. James,
    I was thinking that this approach may work for what I am trying to do as it is very similar to your example. I get a message: "Entity Name specified in FetchXml does not match the entity name in the EntityExpression". At first I thought that maybe your example would only work when using the same entity for the form and fetchXML, but when I tried that I got the same error. Just wondering if you've seem this error before, and if so, what might be the cause - if you have the time.

    Thanks,
    Martin

    ReplyDelete
  4. @Ryan: Try to get the element with "document.getElementById" rather than "Xrm.Page...".

    Cheers
    Christian

    ReplyDelete
  5. I have tried this example. But its not working for me.

    I have used it for Activities subgrid, Nothing happened. Its not updating the subgrid with latest FetchXml..

    Any help much appreciated...

    ReplyDelete
  6. Thanks for the post...

    :( not working for me..its popping error, object required...

    ReplyDelete
  7. This would be really handy, but I cant get it to work.

    ReplyDelete
  8. I get Invalid XML and also the refresh method is not recognized. Any rollup needed?
    The XML I used was downloaded from advanced find, so I'm not sure why it isn't valid.

    ReplyDelete
    Replies
    1. No rollup required, rollup 5 does cause an issue which I'm going to update the post for. Can you send the script that's giving you the problem and I'll take a look

      Delete
  9. Hi,Thanks alot its working fine!!!!

    but one small issue is when I delete record from subgrid ,it delete the record from Main entity or from CRM itself.

    how should I do it?
    means when I delete record from subgrid it should be removed only from that subgrid.

    ReplyDelete
    Replies
    1. That's a tricky one, off the top of my head you'd need to add button to the ribbon that updates a hidden field on the record which is also included in the FetchXml.

      If you need extra assistance let me know and I'll try and knock something up.

      Delete
    2. hi,
      ya plz can u help me in that..if I keep custom button in ribbon say 'Remove' and if user selects the record from subgrid then the Selected Record Ids of a Sub Grid in CRM 2011 using javascript get be achived
      Code Snippet:
      var gridControl = document.getElementById("yourSubGridName").control;
      var ids = gridControl.get_selectedIds();

      but the problem here is how should I remove it from subrid using this ids(can u plz help me in this)...

      one more thing,plz dont mind but the baby in ur snap(photo) is very cute it reminds me on my baby...

      thanks!!!

      Delete
  10. Hi, thanks for the post !
    But I have an issue...
    I have implemented your solution on the account form on wich I have 4 subgrids. It's working fine for two of them but not for the others : document.getElementById("RelatedLeads") returns "null" and the subgrids never refresh...
    I have the rollup 5 installed and regarding your update, I guess this is the cause of the problem.
    Do you have any idea if this issue is corrected with the next rollup ? Or of a a solution to get this fixed ?

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Hi - Great post!

    I am having an issue with getting the grid to display the actual results from the fetchxml. The grid still only shows the default view that is originally assigned to it. I added some alert calls to see if it makes it through the function and it does.

    Any ideas why the default view is still always rendering?

    //Called to create a view for a subgrid Application_Approvals
    function updateApplication_ApprovalsSubGrid() {
    var Application_ApprovalsGrid = document.getElementById("Application_Approvals"); //If this method is called from the form OnLoad, make sure that the grid is loaded before proceeding
    alert(Application_ApprovalsGrid);
    //Included extra null check as a rollup 5 fix
    if (Application_ApprovalsGrid == null || Application_ApprovalsGrid.readyState != "complete") {
    //The subgrid hasn't loaded, wait 1 second and then try again
    setTimeout('updateApplication_ApprovalsSubGrid()', 1000);
    return;
    } //Update the fetchXML that will be used by the grid.
    var fetchXml = "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    fetchXml += "";
    alert(fetchXml);
    Application_ApprovalsGrid.control.setParameter("fetchXml", fetchXml);
    //Force the subgrid to refresh
    Application_ApprovalsGrid.control.refresh();
    alert("refreshed");

    }

    ReplyDelete
    Replies
    1. Jason

      The grid will not be changed on the Create form, this will only work after the record has been saved at least once.

      Without seeing the fetchXml it's difficult to say why it's not refreshing, your alert after the getting the grid is returning the object as you'd expect?

      I'm not sure that this helps but if you want to email me the fetchXml I will take a look.

      Delete
  13. I have RU 6 and I get an error "Can't execute code from a freed script!" I was hoping adding the null check would fix it but it does not. If I take out the refresh the error is gone but my chart does not update. :( Do you think it is because my subgrid is a chart rather than a list? Any ideas would be great! Thank you.

    ReplyDelete
  14. It works,
    i made a generic function out of it
    On change of a picklist item load a custom view .refer the code below

    /////////////////Generic function To change the associated view dynamicaly based on batch process type/////////////////////////////////////////////////////////

    function UpdateSubGrid(sGridName,sCustomviewFetchXML) {

    var TargetGridView = document.getElementById(sGridName);
    //If this method is called from the form OnLoad, make sure that the grid is loaded before proceeding

    if (DonationGrid == null || DonationGrid.readyState != "complete") {
    //The subgrid hasn't loaded, wait 1 second and then try again
    setTimeout('UpdateSubGrid()', 1000);
    return;
    }

    //Inject the new fetchXml
    DonationGrid.control.setParameter("fetchXml", sCustomviewFetchXML);
    //Force the subgrid to refresh
    TargetGridView.control.refresh();
    }
    //////////////////////////////////////// End of function ///////////////////////////////////////////////////////////////////////////////////////////////////////


    //////////////////////EXAMPLE CALL to this Function///////////////////////////////////////////////////////////////////////////

    //Get the Current record id
    var fsCurrentRecordID = Xrm.Page.data.entity.getId();

    //Get the name of Target grid
    var DonationGrid = document.getElementById("Donations");

    //Prepare the Custom view fetchxml
    var fetchxml = ""
    + ""
    + ""
    + ""
    + ""
    + ""
    + ""
    + ""
    + ""
    + ""
    + ""
    + "";

    //Pass these parameters to the generic function
    UpdateSubGrid(DonationGrid,fetchxml);

    ///////////////////////////////////////////End of Example//////////////////////////////////////////////////////////////////////////

    ReplyDelete
  15. I have the similar issue whree I am getting the Insufficient Memory Issue while I tryoin to update any data from the crm screen. Please find the details:
    I have crm 4.0 Onpremise, we have changed the server recently where crm application running.
    We have installed third party tool "Click dimensions" and updated the crm with roll up 21.
    We have add some fields in Entity and then we are geitting this error.
    Kindly suggest what we can do in this case.

    ReplyDelete
  16. I am also facing similar issue. setParameter() method is not cumming in dom tree. So it is throwing an error 'object does,t support propery or method name setParameter()

    ReplyDelete
  17. Thanks for the brilliant customization!

    - My fetch XML's primary entity is 'contact'.
    - I used Stunnware's fetchxml tool to build the following query, which links 'customeraddress' information to the contact.
    - My issue is that, although the subgrid is showing the correct number of rows, it is not showing the desired columns. I suspect the reason is that, since my subgrid is based on the layout of 'Active Contacts', it will only show the columns from this view. Is there a way to create/refer to a custom view?

    Am I fighting a losing battle since customeraddress is not even an entity that can be referred to in the drop-down of entities available from the sub-grid configuration?


















    Cheers!

    function UpdateSubGrid()
    {
    var dupSerGrid = document.getElementById("Addresses_POC");

    //If this method is called from the form OnLoad, make sure that the grid is loaded before proceeding //Included extra null check as a rollup 5 fix
    if (dupSerGrid ==null || dupSerGrid.readyState != "complete")
    {
    //The subgrid hasn't loaded, wait 1 second and then try again
    setTimeout('UpdateSubGrid()', 1000);
    return;
    }

    //Update the fetchXML that will be used by the grid.
    var fetchXml = ""
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += " "
    fetchXml += ""

    //Inject the new fetchXml
    dupSerGrid.control.setParameter("fetchXml", fetchXml);
    //Force the subgrid to refresh
    dupSerGrid.control.refresh();
    }

    ReplyDelete
  18. I kept seeing the code run over and over again. I added the clearTimeout to stop the infinite loop.

    //GLOBAL VARIABLE
    var _sTout;

    if (dupSerGrid ==null || dupSerGrid.readyState != "complete")
    {
    //The subgrid hasn't loaded, wait 1 second and then try again
    _STout = setTimeout('UpdateSubGrid()', 1000);
    return;
    }
    else
    {
    clearTimeout(_STout); //ensures the setTimeout doesn't run again
    }


    ReplyDelete
  19. In CRM 2011 Rollup-12
    subgrid.control.setParameter("fetchXml", fetchXml); is changed to
    subgrid.control.SetParameter("fetchXml", fetchXml);
    same like
    subgrid.control.refresh(); to
    subgrid.control.Refresh();

    All function of subgrid.control will start with capital character

    ReplyDelete