View-FetchXML

You are a Dynamics 365/CDS developer. How you build your FetchXML string in JavaScript/C# code?

Are you use the function: Download Fetch XML in the Advanced Find window?

Advanced Find

Wow, look like you have a lot of tasks 😰 after you Download Fetch XML

  • Open the xml file with the text editor
  • Find " and Replace with '
  • Edit, join to make a correct string, also with a dynamic parameter
  • …..

Instead click the button Download Fetch XML in the Advanced Find window, you can click the button View FetchXML near it by install the solution View-FetchXML

Advanced Find With View-FetchXMl

Ok, What is the difference ? Check the demo

Demo View-FetchXML

The solution View-FetchXML help you

  • Easy copy/paste with 3 types of string: FetchXML, JavaScript and C#
  • Easy edit the dynamic values with fetchData (object JavaScript) or (Anonymous Types C#)

Download

ViewFetchXML_1_3_managed.zip

Hide Next Stage, Set Active, Back Button in the Business Process Flows

I have a requirement in my current project that hide Next Stage, Set Active and Back button in the Business Process Flows

To do that, I used an UnSupported code code below

function hideBPFButton() {
    hideBPFButtons();
    window.addEventListener("resize", hideBPFButtons);
    Xrm.Page.data.process.addOnStageSelected(hideBPFButtons);
}

function hideBPFButtons() {
    var dom = (Xrm == undefined || Xrm.Internal == undefined || Xrm.Internal.isTurboForm() == undefined || Xrm.Internal.isTurboForm() == false) ? document : parent.document;
    $("#stageSetActiveActionContainer", dom).remove();
    $("#stageBackActionContainer", dom).remove();
    $("#stageNavigateActionContainer", dom).remove();
    setTimeout(function () { $("#processStagesContainer", dom).width(1894); }, 50);
}

In the form OnLoad, call function

hideBPFButton();

Before apply code

Before apply code

After apply code

After apply code

How to code: change stage, set active

  • Client side: check Xrm.Page.data.process and Xrm.Page.ui.process
  • Server side: reference 3 fields: processid, stageid and traversedpath: in the entity record

The following code query processid by Process Name in the entity workflow

<fetch distinct="false" mapping="logical" output-format="xml-platform" version="1.0">
  <entity name="workflow">
    <attribute name="workflowid">
    <filter type="and">
      <condition attribute="type" operator="eq" value="1">
      <condition attribute="category" operator="eq" value="4">
      <condition attribute="name" operator="eq" value="yyyyyy">
    </filter>
  </attribute></entity>
</fetch>

The following code query stageid by processid and Stage Name in entity processstage

<fetch distinct="false" mapping="logical" output-format="xml-platform" version="1.0">
  <entity name="processstage">
    <attribute name="processstageid">
    <filter type="and">
      <condition attribute="processid" operator="eq" value="xxxxxx">
      <condition attribute="stagename" operator="eq" value="yyyyyy">
    </filter>
  </attribute></entity>
</fetch>

Checked, Tested work with CRM2016, CRM2016 SP1, CRM2016 Online

UnSupported code, use it with your own risk.

Add more buttons on the form subgrid

Sometime, your business requirement need add some buttons in the form sub-grid like picture below (Account form, sub-grid Contacts). Add more buttons

How I can do that

1. Prepare 2 web-resource png image 16x16 file.

  • 1 for normal button
  • 1 for hover button

2. Copy function below to your main js web-resource file.

function createButton(grid, buttonName, buttonTooltip, buttonImage, buttonImageHover, callback) {
    if (grid == null || grid.length == 0) return;
    if (buttonName == null || buttonName.length == 0) return;
    if (buttonImage == null || buttonImage.length == 0) return;
    var dom = (Xrm == undefined || Xrm.Internal == undefined || Xrm.Internal.isTurboForm() == undefined || Xrm.Internal.isTurboForm() == false) ? document : parent.document;
    var button = dom.getElementById(grid + "_addImageButton");
    if (button == null || button.parentNode == null || button.parentNode.parentNode == null) return;
    var tooltip = "";
    if (buttonTooltip != null && buttonTooltip.length > 0)
        tooltip = " title='" + buttonTooltip + "' alt='" + buttonTooltip + "' ";
    var div = dom.createElement("div");
    div.className = "ms-crm-contextButton";
    div.innerHTML = "<a href='#' id='" + buttonName +"' style='display:block;cursor:pointer;'" + tooltip + "><img id='"+ buttonName +"Image' src='" + buttonImage + "'" + tooltip + "></a>";
    button.parentNode.parentNode.appendChild(div);
    if (buttonImageHover != null) {
        dom.getElementById(buttonName).onmouseover = function () {
            dom.getElementById(buttonName + "Image").src = buttonImageHover;
        }
        dom.getElementById(buttonName).onmouseout = function () {
            dom.getElementById(buttonName + "Image").src = buttonImage;
        }
    }
    dom.getElementById(buttonName).onclick = callback;
}

3. On the on-load form, add the following code to add button to form sub-grid.

createButton("Contacts", "btnViewChart", "View Chart", "../WebResources/pl_chart.png", "../WebResources/pl_chart_hover.png", function() {
    alert("View Chart Click");
});

Function parameters

  • grid: is the name of the sub-grid you add on form, in this case: Contacts, (required)
  • buttonName: because you can add more buttons, so you need enter the unique buttonName, in this case: btnViewChart (required)
  • buttonTooltip: the tooltip of this button, in this case: View Chart (optional)
  • buttonImage: the normal image button that you prepare in step 1, in this case: ../WebResources/pl_chart.png (required)
  • buttonImageHover: the hover button that you prepare in step 1, in this case: ../WebResources/pl_chart_hover.png (optional)
  • callback: a callback function after user click on button. (required)

4. Published and tested. I already tested on CRM2016 SP1 and CRM2016 Online.

NOTE

UnSupported code, use it with your own risk.