Using Advanced Find FetchXml capability in custom forms

I prefer FetchXml compared to QueryExpression or LINQ when writing custom code. Back during the CRM3/4 days there was Stunnware. CRM2011 introduced capability to export the FetchXml directly from the Advanced Find. In CRM 2013/2015 you have four tools, to write and export the FetchXml.

  1. FetchXml Tester (comes with XRMToolBox)
  2. FetchXml Builder
  3. Fetch Tester 3000
  4. CRM DevTools (Chrome only)

The fetchxml I build, is used mostly in a plugin or workflow assembly, but there are times when I want to store the fetchxml in custom entity, and use it a part of scheduled workflow logic. This also needs to be flexible, as I may need to change the fetchxml, without needing to rebuild any assemblies. The obvious and most straight forward way to do this would be to have a textarea field in the form, and copy-paste the fetchxml that was generated from one of this tools, or from the advanced find.

What if there is an better, albeit unsupported way? You can embed the advanced find on the entity form that needs to store the fetchxml, and get the fetchxml from the advanced find, when the user saves the record.

Step 1:
You need two controls: a text area to store the fetchxml and an IFrame that will display the advanced find. The target of the IFrame is “about: blank”. We will set the correct URL using Javascript. I have added the IFrame to a seperate tab, and the default state of this tab is collapsed.

Step 2:
Add the script below as a Javascript webresource and hookup the onSave and onLoad functions to the form save and form load respectively. The id of my IFrame is IFrame_Advanced and the fetchxml is stored in textarea ryr_fetchxml.

var RYR = window.RYR || {};

RYR.onLoad = function(){
  Xrm.Page.getControl('IFRAME_AdvancedFind').setSrc(Xrm.Page.context.getClientUrl()+'/advancedfind/advfind.aspx?pagemode=iframe&navbar=off&cmdbar=false');
};

RYR.onSave = function(){
 var advancedFindFrame = document.getElementById('IFRAME_AdvancedFind').contentWindow;
 advancedFindFrame.ExecuteQuery();
 advancedFindFrame.ShowQuery(); 
 Xrm.Page.getAttribute('ryr_fetchxml').setValue(advancedFindFrame.document.getElementById('FetchXml').value);
};

window.RYR = RYR;

Here is how it looks.

The trick is to call ShowQuery straight after ExecuteQuery, so that div with id FetchXml contains the correct value. If we don’t call the ExecuteQuery, the value of FetchXml won’t be updated when the advanced find is modified by the user.

Once again, this technique is unsupported, so use it at your own risk. I have tested this in Firefox 34 and CRM 2013 6.1.0.581.

UPDATE (24/12/14): There was an issue with the initial script, as it was only working if the organisation was a default one. The initial script split the screen horizontally, if the IFrame url was correctly set using getClientUrl. The updated script fixes this issue. Based on my testing, this is working in Firefox 34, Chrome 39.0.2171.95 and IE 11(in IE9 mode only). One more thing to note -> If the tab with the Advanced Find IFrame doesn’t started out collapsed, the Ribbon Interface of the Advanced Find shows up on the form.

Advertisements

9 thoughts on “Using Advanced Find FetchXml capability in custom forms

  1. It is so nice to me, but in my code it does not work like your result. In Iframe, it just loads “look for and use saved view: and it does not refresh when I choose another entity. Could you review my below code:
    var fetch = window.fetch || {};

    function onLoad (){
    Xrm.Page.ui.controls.get(“IFRAME_IFrame_Advanced”).setSrc(Xrm.Page.context.getClientUrl()+”/advancedfind/advfind.aspx?pagemode=iframe&navbar=off&cmdbar=false”);
    };

    function onSave (){
    var advancedFindFrame = document.getElementById(“IFRAME_IFrame_Advanced”).contentWindow;
    advancedFindFrame.ExecuteQuery();
    advancedFindFrame.ShowQuery();
    Xrm.Page.getAttribute(“new_fetchxmlcontent”).setValue(advancedFindFrame.document.getElementById(“FetchXml”).value);
    };

    window.fetch = fetch;

    • I tested this in Firebug and the script works. Maybe you can put a checkbox in the form which says “Copy Fetchxml” and then move the code that is in the onsave on to the onchange event of this new field. That should give you instant feedback on what fetchxml is generated.

  2. Thanks for the sample but I’m having trouble with the ribbon. If I paste the url into a new tab or window the ribbon is not visible, as expected. However when I load the iframe by expanding the tab, the ribbon switches from the entity’s ribbon to the advanced find ribbon. I tried with and without the RYR namespace. Any ideas on how to keep the entity ribbon?

  3. My entity ribbon was being replaced by the advanced find ribbon on load of the iframe. Managed to stop the ribbon switching by writing a web resource that contained an iframe instead of using an iframe directly. Thanks for the code!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s