Category Archives: JavaScript

Create N to N relationship in Javascript (Associate and Dissasociate)

To associate and dissasocite N to N relationships I found this very usefull libraries thanks to Dave Berry.

To use it we simply have to call:


//AssociateEntities(relationshipSchemaName, entity1SchemaName, entity1KeyValue, entity2SchemaName, entity2KeyValue, skipCheck)

AssociateEntities("lema_lema_sitevisit_epa_noncompliance", "epa_noncompliance", CIID, "lema_sitevisit", createResponse, true);

Find here the Associate Library. As usual I upload it as a .doc file. Rename it to .js to view it.

Query N to N relationship in Javascript

Using this function we will be able to query N to N relationshipt in JS


//Main function

function Main()
{
   var sectors = getSectorsFromAnnualPlan(AnnualPlanId);

    if (sectors.length > 0) {
        logMessage += 'For each Sector:\n';
    }

    for (var k = 0; k < sectors.length; k++) {
        var sectorguid = sectors[k].childNodes[0].text;
        var sectorName = sectors[k].childNodes[1].text;
}

}

//Calling function
function getSectorsFromAnnualPlan(annualplanid) {

    var EntityName = "lema_sector";
    var AttributeList = new Array();
    AttributeList[0] = "lema_sectorid";
    AttributeList[1] = "lema_name";
    AttributeList[2] = "lema_sectoroption";
    var RetrieveDistinct = false;
    var LinkFromEntityName = "lema_sector";
    var LinkFromAttributeName = "lema_sectorid";
    var LinkToEntityName = "lema_annualsitevisitsplan_lema_sector";
    var LinkToAttributeName = "lema_sectorid"
    var LinkEntityFilterAttributeName = "lema_annualsitevisitsplanid";
    var LinkEntityFilterAttributeValue = annualplanid; //set the initial entity GUI

    var responseXml = RetrieveMultipleFromLinkEntity(EntityName, AttributeList, false, LinkFromEntityName
                                                , LinkFromAttributeName, LinkToEntityName, LinkToAttributeName
                                                , LinkEntityFilterAttributeName, LinkEntityFilterAttributeValue);

    return responseXml;
}

//Retreive Function

function RetrieveMultipleFromLinkEntity(entityName, arrColumnName, enableDistinct, linkFromEntityName, linkFromAttributeName, linkToEntityName, linkToAttributeName, linkEntityFilterAttributeName, linkEntityFilterAttributeValue) {

    if ((entityName != null) && (entityName.length > 0) && (arrColumnName != null) && (arrColumnName.length > 0) &&
    (linkFromEntityName != null) && (linkFromEntityName.length > 0) && (linkFromAttributeName != null) && (linkFromAttributeName.length > 0) &&
    (linkToEntityName != null) && (linkToEntityName.length > 0) && (linkToAttributeName != null) && (linkToAttributeName.length > 0) &&
    (linkEntityFilterAttributeName != null) && (linkEntityFilterAttributeName.length > 0) && (linkEntityFilterAttributeValue != null) && (linkEntityFilterAttributeValue.length > 0)) {

        var ColumnsSetAttributes = '';
        var IsDistinctValue = false;

        // Build columns to be retrieved
        for (var i = 0; i < arrColumnName.length; i++) {
            ColumnsSetAttributes += " " + arrColumnName[i] + ""
        }

        //Set Distinct value
        if (enableDistinct != null && typeof (enableDistinct) != "undefined" && (enableDistinct == "true" || enableDistinct == true)) {
            IsDistinctValue = true;
        }

        // Build link entity filter
        var LinkFilterCondition = " " +
                " " + linkEntityFilterAttributeName + "" +
                " Equal" +
                " " +
                " " + linkEntityFilterAttributeValue + "" +
                " " +
                " ";

        var xml = "<!--?xml version=\"1.0\" encoding=\"utf-8\"?-->" +
         "" +
         GenerateAuthenticationHeader() +
         " " +
         " " +
         " " +
         " " + entityName + "" +
         " " +
         " " +
         ColumnsSetAttributes +
         " " +
         " " +
         " " + IsDistinctValue + "" +
         " " +
         " " +
         " " + linkFromAttributeName + "" +
         " " + linkFromEntityName + "" +
         " " + linkToEntityName + "" +
         " " + linkToAttributeName + "" +
         " Inner" +
         " " +
         " And" +
         " " +
         LinkFilterCondition +
         " " +
         " " +
         " " +
         " " +
         " " +
         " " +
         " " +
         "";

        var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
        xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
        var oXml;

        try {
            xmlHttpRequest.send(xml);
            oXml = xmlHttpRequest.responseXML;

            // Check for errors.
            if (oXml != null) {
                var errorCount = oXml.selectNodes('//error').length;
                if (errorCount != 0) {
                    var msg = oXml.selectSingleNode('//description').nodeTypedValue;
                    alert(msg);
                }
                else {
                    //return the Business Entity node
                    return oXml.selectNodes("//BusinessEntity");
                }
            }
            else {
                alert("Error: No response received.");
            }
        }
        catch (e) {
            if (oXml != null) {
                var err = oXml.getElementsByTagName("description")[0].childNodes[0].nodeValue;
                alert("Error: " + e.description + ": " + err);
            }
            else {
                alert("Error: Unexpected error occurred.");
            }
        }
    }
    return null;
}

The fetch code is not complete so here NtoNquery you can find the full code in an attachment. As usuall WordPress dont allow me to upload .js files so donwload it and rename it to .js or .txt to view it.

Autopopulate Activity Party Using Query String

In the target form properties we have set up 2 parameters . Every Parameter needs to have a _ in its name.

  • lema_ciname — Type string
  • lema_ciguid — Type uniqid

Then we can call that form from any external application with :

// Type can be CI Action 919780000 && CI Intruction 919780001
function OpenTaskCreation(CIGuid, CIName,Type) {

    var features = "location=no,menubar=no,status=no,toolbar=no,resizable=yes";

    //Encode Guid of regardingObject to set -- lema_ciname , lema_ciguid
    var extraqs = "lema_ciname=" + CIName;
    extraqs += "&lema_ciguid=" + CIGuid;
    extraqs += "&epa_tasktype=" + Type;

    var features = "location=no,menubar=no,status=no,toolbar=no";

    var serverurl = "http://serverrurl/org";
     // Open the window.
     window.open( serverurl + "/main.aspx?etn=task&pagetype=entityrecord&extraqs=" +
     encodeURIComponent(extraqs), "_blank", features, false);

}

Then, in the form that we are calling we register a js function on the onload event.


function OnSiteVisitTaskLoad() {
    var urlParams = Xrm.Page.context.getQueryStringParameters();
    var ciname = urlParams['lema_ciname'];
    var ciguid = urlParams['lema_ciguid'];

    var partlistData = new Array();
        partlistData[0] = new Object();
        partlistData[0].id = ciguid;
        partlistData[0].name = ciname;
        partlistData[0].entityType = "epa_complianceinvestigation";
        Xrm.Page.getAttribute("regardingobjectid").setValue(partlistData);

    }

This is creation of parameters is only needed to autopopulate Activity parties. For other fields we could use something like.


function OpenNCCreation(LicenceGuid, LicenceName) {

    //Set the values of epa_licenceid field.
    var extraqs = "epa_licenceid={" + LicenceGuid + "}";
    extraqs += "&epa_licenceidname=" + LicenceName;

    var features = "location=no,menubar=no,status=no,toolbar=no";
    // Open the window.
    window.open("/main.aspx?etn=epa_noncompliance&pagetype=entityrecord&extraqs=" +
     encodeURIComponent(extraqs), "_blank", features, false);

}

More info about Prepopulating creation forms here or in this Microsoft post.

CRM 2011 Javascript – working with Option sets

If we want to write the value of an option set in a text field.

 
function onyearchange() {
    var myOptionSet = Xrm.Page.data.entity.attributes.get("lema_year");
    var optionSetText = myOptionSet.getText();
    Xrm.Page.getAttribute("lema_name").setValue(optionSetText);
}

If we need to set the value of an option set based on a text

 

function SetOptionSetValueByText(optionsetAttribute, optionText)  
 {  
  var options = Xrm.Page.getAttribute(optionsetAttribute).getOptions();  
  for(i = 0; i < options.length; i++)  
  {  
  if (options[i].text == optionText)  
   Xrm.Page.getAttribute(optionsetAttribute).setValue(options[i].value);  
  }  
 }  



SetOptionSetValueByText("lema_year","2014");

Call Workflow from Javascript

This is the code needed.


function triggerBulkWorkflowByName(wfName, svid) {
    var wId = getWorkflowId(wfName);
    triggerWorkflow(wId, svid);
}

function getWorkflowId(wfName) {

    var urlPos = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/WorkflowSet?$filter=Name eq '" + wfName + "' and ParentWorkflowId/Id eq null";
    //var urlPos = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/WorkflowSet";

    var id;

    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        async: false,
        datatype: "json",
        url: urlPos,
        beforeSend: function (XMLHttpRequest) {
            //Specifying this header ensures that the results will be returned as JSON.
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
            if (data.d.results.length > 0) {
                id = data.d.results[0].WorkflowId;
            }
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert("Error");

        }
    });

    return id;
}

function triggerWorkflow(wfId, entityId) {

    try {
var soapBody = "<soap:Body>" + 
" <Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
 " <Request xsi:type=\'ExecuteWorkflowRequest\'>" +
 " <EntityId>" + entityId + "</EntityId>" +
 " <WorkflowId>" + wfId + "</WorkflowId>" +
 " </Request>" +
 " </Execute>" +
 "</soap:Body>";

/*Wrap the Soap Body in a soap:Envelope.*/
 var soapXml = "<soap:Envelope " +
 " xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' " +
 " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
 " xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
 GenerateAuthenticationHeader() +
 soapBody +
 "</soap:Envelope>";

        /* Create the XMLHTTP object for the execute method.*/
        var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        xmlhttp.open("POST", "/MSCRMservices/2007/crmservice.asmx", false);
        xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        /* Send the XMLHTTP object. */
        xmlhttp.send(soapXml);
    }

    catch (e) {
        alert("An error has occured: " + e.description);
    }

}

How to generate Fetch XML from LINQ using LinqPad

Linqpad is a great tool to query any system using LINQ.

Fetch XML with LinqPad

Fetch XML with LinqPad

If we want to use this tool connected with CRM we need to install a plugin that you can get by going to the downloads tab in the following site.

Generating Fetch From Linq

Once we have LinqPad properly installed and we are able to query results in CRM it would be great to be able to convert those Linqueries into Fetch. To do so we can follow the instructions described by Keydet (Microsoft Employee) in this great post.

Basically we need to add into “My Extensions File” the following code in the MyExtensions class.

public static class MyExtensions
{
	public static string ToFetchXml(this IQueryable linqQuery, dynamic orgService)
	{
		var queryExpression = GetQueryExpression(linqQuery);
	
		var expressionToFetchXmlRequest = new Microsoft.Crm.Sdk.Messages.QueryExpressionToFetchXmlRequest
		{
		Query = queryExpression
		};
	
		var organizationResponse = (Microsoft.Crm.Sdk.Messages.QueryExpressionToFetchXmlResponse)orgService.Execute(expressionToFetchXmlRequest);
	
		return organizationResponse.FetchXml;
	}
 
	private static Microsoft.Xrm.Sdk.Query.QueryExpression GetQueryExpression(IQueryable linqQuery)
	{
		object projection = null;
		object source = null;
		object linkLookups = null;
		bool flag = false;
		bool flag2 = false;
	
		object[] arguments = new object[6];
		arguments[0] = (object)linqQuery.Expression;
		arguments[1] = (object)flag;
		arguments[2] = (object)flag2;
		arguments[3] = (object)projection;
		arguments[4] = (object)source;
		arguments[5] = (object)linkLookups;
	
		Microsoft.Xrm.Sdk.Query.QueryExpression query = (Microsoft.Xrm.Sdk.Query.QueryExpression)linqQuery.Provider.GetType().InvokeMember("GetQueryExpression", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, linqQuery.Provider, arguments);
		return query;
	}
	
}

Then pressing F4 we need to add 3 libraries (Microsoft.crm.sdk.proxy , microsoft.xrm.sdk and System.Runtime.Serialization (.NET 4.0)) and then we will be able to get the Fetch XML from the query by adding .ToFetchXML(this) to any LinQ statement between parentesis as shown in the image:


(from cm in lema_controlmeasureSet
join intersect in lema_controlmeasure_hazardouseventrevisionSet on cm.Id equals intersect.lema_controlmeasureid.Value
join he in lema_hazardouseventrevisionSet on intersect.lema_hazardouseventrevisionid.Value equals he.Id
where (he.lema_status.Value == 3 || he.lema_status.Value == 4)
select cm).ToFetchXml(this)

Getting QueryExpression from FetchXML

Now from any LinQ we can get easily our FetchXML. Then using the CRM2011 SDK we can easily generate QueryExpresions from Fetch as described here.

I think this was helpfull!!

Regards,

Miguel

Convert Text Field to Hyperlink


function ConvertToLink(fldName) {
    if(Xrm.Page.getAttribute(fldName).getValue()!=null)
    {
        var content = Xrm.Page.getAttribute(fldName).getValue();
        var btn = "<a href='javascript: void(0);' onclick=\"window.open(\'" + content + "\', \'windowname1\', \'width=600, height=650\');  return false;\" style='color:blue;text-decoration:underline !important'>" + content +"</a>";
        var ctrl = Xrm.Page.ui.controls.get(fldName)._control;
        // Add the new button 
        ctrl.get_element().innerHTML += btn;
        // Hide the textbox 
        ctrl.get_element().firstChild.style.display = 'none';
    }
}