JAVASCRIPT Archives - Microsoft Dynamics 365 Blog http://microsoftdynamics.in/category/javascript/ Microsoft Dynamics CRM . Microsoft Power Platform Sat, 27 May 2023 07:41:24 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/04/cropped-Microsoftdynamics365-blogs.png?fit=32%2C32 JAVASCRIPT Archives - Microsoft Dynamics 365 Blog http://microsoftdynamics.in/category/javascript/ 32 32 176351444 executioncontext.getformcontext is not a function : Microsoft dynamics CRM Error http://microsoftdynamics.in/2023/05/27/executioncontext-getformcontext-is-not-a-function-microsoft-dynamics-crm-error/ Sat, 27 May 2023 07:41:24 +0000 http://microsoftdynamics.in/?p=4749 When Calling javaScript Function from Ribbon button , you might get error executioncontext.getformcontext is not a function  because Primarycontrol gives Form context not the execution context. Error screenshot. Below is the full Error : TypeError: executionContext.getFormContext is not a function at SetUppercase (https://***.crm.dynamics.com/%7B636700249930001087%7D/WebResources/***_Common.js?ver=2021682843:19:40) at eval (eval at RunHandlerInternal (https://***.crm.dynamics.com/form/ClientApiWrapper.aspx?ver=2021682843:153:1), <anonymous>:1:1) at RunHandlerInternal (https://***.crm.dynamics.com/form/ClientApiWrapper.aspx?ver=2021682843:159:1) at RunHandlers...

The post executioncontext.getformcontext is not a function : Microsoft dynamics CRM Error appeared first on Microsoft Dynamics 365 Blog.

]]>
When Calling javaScript Function from Ribbon button , you might get error executioncontext.getformcontext is not a function  because Primarycontrol gives Form context not the execution context.

Error screenshot.

Below is the full Error :

TypeError: executionContext.getFormContext is not a function
at SetUppercase (https://***.crm.dynamics.com/%7B636700249930001087%7D/WebResources/***_Common.js?ver=2021682843:19:40)
at eval (eval at RunHandlerInternal (https://***.crm.dynamics.com/form/ClientApiWrapper.aspx?ver=2021682843:153:1), <anonymous>:1:1)
at RunHandlerInternal (https://***.crm.dynamics.com/form/ClientApiWrapper.aspx?ver=2021682843:159:1)
at RunHandlers (https://***.crm.dynamics.com/form/ClientApiWrapper.aspx?ver=2021682843:118:1)
at ExecuteHandler (https://***.crm.dynamics.com/form/ClientApiWrapper.aspx?ver=2021682843:81:1)
at Mscrm.TurboForm.Control.CustomScriptsManager.$De_1 (https://***.crm.dynamics.com/_static/form/formcontrols.js?ver=2021682843:5093:100)
at Mscrm.TurboForm.Control.CustomScriptsManager.executeHandler (https://***.crm.dynamics.com/_static/form/formcontrols.js?ver=2021682843:5031:18)
at Mscrm.TurboForm.Control.CustomScriptsManager.executeHandlerByDescriptor (https://***.crm.dynamics.com/_static/form/formcontrols.js?ver=2021682843:5062:18)
at https://***.crm.dynamics.com/_static/form/formcontrols.js?ver=2021682843:5073:19
at https://***.crm.dynamics.com/_common/global.ashx?ver=2021682843:6823:193161

 

 

SOLUTION :

follow the link : http://microsoftdynamics.in/2020/08/22/error-getformcontext-is-not-a-function-in-uci-ribbon-button/

The post executioncontext.getformcontext is not a function : Microsoft dynamics CRM Error appeared first on Microsoft Dynamics 365 Blog.

]]>
4749
Best Way to use Force Save JavaScript client API in Microsoft dynamics CRM http://microsoftdynamics.in/2020/09/30/best-way-to-use-force-save-javascript-client-api-in-microsoft-dynamics-crm/ Tue, 29 Sep 2020 19:08:22 +0000 http://microsoftdynamics.in/?p=4207 The post Best Way to use Force Save JavaScript client API in Microsoft dynamics CRM appeared first on Microsoft Dynamics 365 Blog.

]]>

We know how data. save work but in post, we will see how to perform further logic on successful save or failure of function

formContext.data.save(saveOptions).then(successCallback, errorCallback);

We have triggered a function on change of name, once the name is changed javascript will try to force save the form using below client API

 formContext.data.save().then(function() { alert("Successfully Saved "); }, function() { alert("Something Went Wrong"); });
  1. We have a mandatory field on the lead, when we change the name and the mandatory field is empty alert msg will be empty.

  2. If Everything goes fine .then(function() { alert(“Successfully Saved “); }

The post Best Way to use Force Save JavaScript client API in Microsoft dynamics CRM appeared first on Microsoft Dynamics 365 Blog.

]]>
4207
JavaScript- Download Report as PDF , Attach Report to SharePoint or notes http://microsoftdynamics.in/2020/08/29/javascript-download-report-as-pdf-attach-report-to-sharepoint-or-notes/ Sat, 29 Aug 2020 15:36:08 +0000 http://microsoftdynamics.in/?p=4113 JavaScript- Download Report as PDF , Attach Report to SharePoint or notes

The post JavaScript- Download Report as PDF , Attach Report to SharePoint or notes appeared first on Microsoft Dynamics 365 Blog.

]]>

Using JavaScript Download or save any report to Sharepoint or notes Latest 2020

This Post contains unexplained and with not best practice code, in the coming days I will refine this.

This is not Step by Step Guide and not connected, will update the post again

Also not necessary use this in UCI , it only for knowledge sharing and for UCI there many other OOB alternatives as well, will share the link Soon

1. Get Report Session

    getReportingSession: function () {

        var retrieveEntityReq = parent.document.getElementById("IFRAME_expiryreport").contentWindow.document.getElementById("resultFrame").contentWindow.document.documentElement.innerHTML;
        var x = retrieveEntityReq.lastIndexOf("ReportSession="); var y = retrieveEntityReq.lastIndexOf("ControlID=");
        var ret = new Array();
        ret[0] = retrieveEntityReq.substr(x + 14, 24); ret[1] = retrieveEntityReq.substr(x + 10, 32);
        return ret;
    },
    convertResponseToPDF: function (newPth) {
        //Create query string that will be passed to Report Server to generate PDF version of report response.
        //var pth = Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + arrResponseSession[0] + "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + arrResponseSession[1] + "&OpType=Export&FileName=Public&ContentDisposition=OnlyHtmlInline&Format=PDF";
        var pth = newPth;

        //Create request object that will be called to convert the response in PDF base 64 string.
        var retrieveEntityReq = new XMLHttpRequest();
        retrieveEntityReq.open("GET", pth, true);
        retrieveEntityReq.setRequestHeader("Accept", "*/*");
        retrieveEntityReq.responseType = "arraybuffer";
        retrieveEntityReq.onreadystatechange = function () { // This is the callback function.
            if (retrieveEntityReq.readyState == 4 && retrieveEntityReq.status == 200) {
                var binary = "";
                var bytes = new Uint8Array(this.response);
                for (var i = 0; i < bytes.byteLength; i++) {
                    binary += String.fromCharCode(bytes[i]);
                }
                //This is the base 64 PDF formatted string and is ready to pass to the action as an input parameter.
                var base64PDFString = btoa(binary);
                //4. Call Action and pass base 64 string as an input parameter. That’s it
                Xrm.Utility.showProgressIndicator("Converted report to PDF. Please Wait..");

                var note = {};
                var recordId = Xrm.Page.data.entity.getId();
                recordId = recordId.replace('{', '').replace('}', '');

                var NotificName = Xrm.Page.getAttribute("uniquefield").getValue();

                var refInvoice = new Object();
                refInvoice.LogicalName = "Logical name";
                refInvoice.Id = recordId;

                note.ObjectId = refInvoice;
                note.ObjectTypeCode = refInvoice.LogicalName;

                note.Subject = "ContractExpiryLetter: " + NotificName;
                note.MimeType = "application/pdf";
                note.DocumentBody = base64PDFString;
                note.FileName = NotificName + ".pdf";

                XrmServiceToolkit.Rest.Create(
                    note,
                    "AnnotationSet",
                    function (result) {
                        //Alert user
                        //alert("Note Created");
                        Xrm.Utility.closeProgressIndicator();
                        //Refresh data so user sees newly created note
                        Xrm.Page.data.refresh(false);

                    },
                    function (error) {
                        Xrm.Utility.closeProgressIndicator();
                        alert(error.message);
                    },
                    true
                );
            }
        };
        //This statement sends the request for execution asynchronously. Callback function will be called on completion of the request.
        retrieveEntityReq.send();
    }

2. Run Report to Print
runReportToPrint: function () {


        var params = quoteInvoice.getReportingSession();
        var newPth = Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + params[0] + "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + params[1] + "&OpType=Export&FileName=public&ContentDisposition=OnlyHtmlInline&Format=PDF";
        quoteInvoice.convertResponseToPDF(newPth);
        //window.open(newPth, "_self");
    },

    callActionOnButtonClick: function (data) {

        //// GUID Validation
        if (!quoteInvoice.isGuid(entityId)) {
            alert("ID is Invalid GUID.");
            Xrm.Utility.closeProgressIndicator();
            return;
        }
    },

    isGuid: function (value) {
        /// <summary>
        /// Checks whether value is type of GUID or not.
        /// </summary>
        /// <param name="value" type="type"></param>
        /// <returns type=""></returns>
        var validGuid = new RegExp("^({|()?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(}|))?$")
        if (value && typeof value === "string" && validGuid.test(value)) {
            return true;
        }
        return false;
    }

};
3. Get Doc Library or Create Doc Library Sharepoint
DocLibrary = {
    CheckDocumentLibraryAvailable: function () {

        var fetchXmlQuery =
            "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
            "  <entity name='sharepointdocumentlocation'>" +
            "    <attribute name='relativeurl' />" +
            "    <attribute name='regardingobjectid' />" +
            "    <attribute name='parentsiteorlocation' />" +
            "    <attribute name='absoluteurl' />" +
            "    <attribute name='name' />" +
            "    <attribute name='sharepointdocumentlocationid' />" +
            "    <order attribute='name' descending='false' />" +
            "    <filter type='and'>" +
            //"      <condition attribute='ownerid' operator='eq-userid' />" +
            "      <condition attribute='statecode' operator='eq' value='0' />" +
            "      <condition attribute='locationtype' operator='eq' value='0' />" +
            "      <condition attribute='servicetype' operator='eq' value='0' />" +
            "      <condition attribute='regardingobjectid' operator='eq' uiname='test' uitype='" + Xrm.Page.data.entity.getEntityName() + "' value='" + Xrm.Page.data.entity.getId() + "' />" +
            "    </filter>" +
            "  </entity>" +
            "</fetch>";

        var req = new XMLHttpRequest();
        req.open(
            "GET",
            Xrm.Page.context.getClientUrl() +
            "/api/data/v9.0/sharepointdocumentlocations?fetchXml=" +
            encodeURIComponent(fetchXmlQuery),
            false
        );
        req.setRequestHeader("Prefer", 'odata.include-annotations="*"');
        req.onreadystatechange = function () {
            if (this.readyState === 4) {
                req.onreadystatechange = null;
                if (this.status === 200) {

                    var results = JSON.parse(this.response);
                    //console.dir(results);
                    if (results.value.length > 0) {
                        return;
                    }
                    else {
                        DocLibrary.CreateDocumentLibrary();
                    }
                } else {
                    alert(this.statusText);
                }
            }
        };
        req.send();

    },

    CreateDocumentLibrary: function () {
        debugger;
        var locationid = '';
        var fetchXmlQuery =
            "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
            "  <entity name='sharepointdocumentlocation'>" +
            "    <attribute name='relativeurl' />" +
            "    <attribute name='regardingobjectid' />" +
            "    <attribute name='parentsiteorlocation' />" +
            "    <attribute name='absoluteurl' />" +
            "    <attribute name='name' />" +
            "    <attribute name='sharepointdocumentlocationid' />" +
            "    <order attribute='name' descending='false' />" +
            "    <filter type='and'>" +
           // "      <condition attribute='ownerid' operator='eq-userid' />" +
            "      <condition attribute='statecode' operator='eq' value='0' />" +
            "      <condition attribute='locationtype' operator='eq' value='0' />" +
            "      <condition attribute='servicetype' operator='eq' value='0' />" +
            "      <condition attribute='relativeurl' operator='eq' value='" + Xrm.Page.data.entity.getEntityName() + "' />" +
            "    </filter>" +
            "    <link-entity name='sharepointsite' from='sharepointsiteid' to='parentsiteorlocation' link-type='inner' alias='ac' />" +
            "  </entity>" +
            "</fetch>";

        var req = new XMLHttpRequest();
        req.open(
            "GET",
            Xrm.Page.context.getClientUrl() +
            "/api/data/v9.0/sharepointdocumentlocations?fetchXml=" +
            encodeURIComponent(fetchXmlQuery),
            false
        );
        req.setRequestHeader("Prefer", 'odata.include-annotations="*"');
        req.onreadystatechange = function () {
            if (this.readyState === 4) {
                req.onreadystatechange = null;
                if (this.status === 200) {

                    var results = JSON.parse(this.response);
                    //console.dir(results);
                    if (results.value.length > 0) {
                        locationid = results.value[0].sharepointdocumentlocationid;
                    }
                    else {
                        alert('Unable to check the Sharpoint integration. Please contact administrator.');
                    }
                } else {
                    alert(this.statusText);
                }
            }
        };
        req.send();



        var relativepath = Xrm.Page.data.entity.getId().replace("{", "").replace("}", "").replace("-", "").replace("-", "").replace("-", "").replace("-", "");
        var absolutepath = DocLibrary.ConstructPath(locationid);

        var locationdetails = {
            "LocationName": "Location 1",
            "AbsUrl": absolutepath + relativepath,
            "RelativePath": relativepath,
            "ParentType": "sharepointdocumentlocation",
            "ParentId": locationid,
            "IsAddOrEditMode": true,
            "IsCreateFolder": true,
            "DocumentId": "",
            "ParentEntityReference": { "@odata.type": "Microsoft.Dynamics.CRM." + Xrm.Page.data.entity.getEntityName() }
        };
        locationdetails["ParentEntityReference"][Xrm.Page.data.entity.getEntityName() + "id"] = Xrm.Page.data.entity.getId();

        var createReq = new XMLHttpRequest();
        createReq.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.0/AddOrEditLocation", false);
        createReq.setRequestHeader("OData-MaxVersion", "4.0");
        createReq.setRequestHeader("OData-Version", "4.0");
        createReq.setRequestHeader("Accept", "application/json");
        createReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        createReq.onreadystatechange = function () {
            if (this.readyState === 4) {
                createReq.onreadystatechange = null;
                Xrm.Utility.closeProgressIndicator();
                if (this.status === 200) {
                    //Success - No Return Data - Do Something
                } else {
                    Xrm.Utility.alertDialog(this.statusText);
                }
            }
        };
        createReq.send(JSON.stringify(locationdetails));
    },
4. Upload Function
UploadDocument: function (filename, base64PDFString) {

        var parameters = {
            "Content": base64PDFString,
            "Entity": {
                "@odata.type": "Microsoft.Dynamics.CRM.sharepointdocument",
                "locationid": "",
                "title": filename + ".pdf"
            }, "OverwriteExisting": true,
            "ParentEntityReference": {
                "@odata.type": "Microsoft.Dynamics.CRM." + Xrm.Page.data.entity.getEntityName()

            }, "FolderPath": ""
        };

        parameters["ParentEntityReference"][Xrm.Page.data.entity.getEntityName() + "id"] = Xrm.Page.data.entity.getId();


        var req = new XMLHttpRequest();
        req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.0/UploadDocument", true);
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.onreadystatechange = function () {
            if (this.readyState === 4) {
                req.onreadystatechange = null;
                if (filename.indexOf("OppSummary") == -1)
                    Xrm.Utility.closeProgressIndicator();
                if (this.status === 204) {
                    //Success - No Return Data - Do Something
                } else {
                    Xrm.Utility.alertDialog(this.statusText);
                }
            }
        };
        req.send(JSON.stringify(parameters));
    }
};

As Mention above is not in Steps or Connected, I Will add steps soon. thanks

The post JavaScript- Download Report as PDF , Attach Report to SharePoint or notes appeared first on Microsoft Dynamics 365 Blog.

]]>
4113
Call Power Automate Flow from JavaScript from CRM || Execute Power Automate Flow from JavaScript and Get Response back in CRM Form, On-demand Power Automate flow from button http://microsoftdynamics.in/2020/08/23/execute-power-automate-flow-from-javascript-and-get-response-back-in-crm-form-on-demand-power-automate-flow-from-button/ Sun, 23 Aug 2020 14:53:28 +0000 http://microsoftdynamics.in/?p=4095 Call Power Automate Flow from JavaScript from CRM

1. "Execute Flow button" is Clicked from CRM
2. JS will execute Power Automate Flow using XMLHttpRequest
3.. Power Automate is Configured to send Response with Status 200 if condition fail or successful.
4. Js receives the Response and shows message as alert.

and all these activities will happen real-time

The post Call Power Automate Flow from JavaScript from CRM || Execute Power Automate Flow from JavaScript and Get Response back in CRM Form, On-demand Power Automate flow from button appeared first on Microsoft Dynamics 365 Blog.

]]>

Scenario is

1. "Execute Flow button" is Clicked from CRM
2. JS will execute Power Automate Flow using XMLHttpRequest
3.. Power Automate is Configured to send Response with Status 200 if condition fail or successful.
4. Js receives the Response and shows message as alert.

and all these activities will happen realtime

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/08/ondemand-PowerAutomate-flow-using-javascript-ribboon-button-dvmske.png?fit=1195%2C802

The post is Divided into 2 Parts

  1. Executing PowerAutomate Flow from Button using javascript
  2. Configuring response action in Power automate and Capturing response message in CRM using javascript

Step1 : Executing PowerAutomate Flow from Button using javascript

We will action “When an Http Request is received ” and follow below steps

  1. Create Power automate Flow to receive HTTPS Request from Javascript and send Email
  2. Register Javascript
  3. Creating a Ribbon Button on Contact Entity and add javascript action to the button Command and pass PrimaryControl

As in our previous post we already mentions steps to register and use it in Javascript

Click Here : http://microsoftdynamics.in/2020/07/11/execute-microsoft-power-automate-from-ribbon-using-javascript-on-demand-power-automate-flow-using-javascript-in-uci-replace-ribbonaction-js/

Below code open request to execute power automate flow, Next step is to see how we can get Response message in JS

function readXML(executionContext) {   
var formContext = executionContext.getFormContext();
    var flowUrl = "Http Post URL";
    var input = JSON.stringify({
        "contactid": formContext .data.entity.getId().replace("{", "").replace("}", "")
    });
    var req = new XMLHttpRequest();
    req.open("POST", flowUrl, true);
    req.setRequestHeader('Content-Type', 'application/json');
    req.send(input);
}

Step2 : Add response Action in Power Automate Flow

In Step1, we had executed XMLHttpRequest and have not written code to get a response in JS, In this step we will add custom response message which we will get in Javascript .

  1. Adding action “when a HTTP request is received”, setup payload
  2. Adding Condition “1 = 1”
  3. Adding Response action with Status = 200 and Body with Message “Yes Condition”

Step3 : Get Response in Javascript

We have requested XMLHttpRequest to Execute Flow, Adding custom response msg in Power Automate,

Now we will use blow code to get response with status 200 in CRM

function readXML(executionContext) {   
var formContext = executionContext.getFormContext();
    var flowUrl = "Http Post URL";
    var input = JSON.stringify({
        "contactid": formContext .data.entity.getId().replace("{", "").replace("}", "")
    });
    var req = new XMLHttpRequest();
    req.open("POST", flowUrl, true);
    req.setRequestHeader('Content-Type', 'application/json');

////Response
req.onreadystatechange = function () {
        if (this.readyState === 4) { 
            req.onreadystatechange = null;
            if (this.status === 200) {
                var result = this.response; 
                alert("" + result); 
            }
            else if(this.status === 400){
                alert(this.statusText);
  var result = this.response; 
                alert("Error" + result);
            }
        }
    };  

////End
    req.send(input);
}

We can write the code to get request and get response Asynchronous or Synchronous Thanks

The post Call Power Automate Flow from JavaScript from CRM || Execute Power Automate Flow from JavaScript and Get Response back in CRM Form, On-demand Power Automate flow from button appeared first on Microsoft Dynamics 365 Blog.

]]>
4095
Migration from Legacy WebClient to UCI – Deprecated Javascript (Client Api) Collection Book , Replace Deprecated Client API To New and latest Client Api’s http://microsoftdynamics.in/2020/08/22/migration-from-legacy-webclient-to-uci-deprecated-javascript-client-api-collection-book-replace-deprecated-client-api-to-new-and-latest-client-apis/ Sat, 22 Aug 2020 12:05:40 +0000 http://microsoftdynamics.in/?p=4081 The post Migration from Legacy WebClient to UCI – Deprecated Javascript (Client Api) Collection Book , Replace Deprecated Client API To New and latest Client Api’s appeared first on Microsoft Dynamics 365 Blog.

]]>

Most of us are already using updated client API and replacing example like xrm.page to FormContext, Below is

1. How to replace Deprecated Client API Javascript with New

2. Full Deprecated to New client API Table

There are some big changes in Client API and most of them are as below

  • Execution Context: Context of any item on the form (Xrm.Page)
  • Global Context: utility to retrieve org Information example, userID e.t.c  (Xrm.utility)
  • Deprecated Client Apis and Intrrotucing some new

We will Divide the post in 2 parts

  1. Replace Deprecated Client API To New and latest Client Api’s
  2. Full Deprecated Client API vs new and Latest Client API’S Table

Check1: How to Replace Deprecated Client Apis to New

  1. First approach is to use Upgrade examiner, please check out our last blog as below how to use Fast track and use upgrade examiner as a starter.

    Click Here: http://microsoftdynamics.in/2020/07/16/migration-from-legacy-webclient-to-uci-ask-for-fasttrack-and-upgrade-examiner-not-confident-on-transition-ask-microsoft/

  2. Once you changed the latest client API’s there is a major change with Xrm.Page
    -> 1st enable checkbox ” Pass execution context as the first Parameter -> ExecutionContext is Automatically passed as 1st parameter as below

Check2: Full Deprecated Client API vs new and Latest Client API'S Table

Objective Using Xrm.Page (Deprecated Client API) Using formContext (Replacement Client API)
Simple JavaScript function function demoFunction(){ } function demoFunction(eContext){
//Get form context
var formContext = eContext.getFormContext();
}
Disable/lock field, “addRegions”, for selection Xrm.Page.getControl("addRegions").
setDisabled(true);
formContext.getControl("addRegions").
setDisabled(true);
Enable/unlock field, “addRegions”, for selection Xrm.Page.getControl("addRegions").
setDisabled(false);
formContext.getControl("addRegions").
setDisabled(false);
Hide field, “addRegions” Xrm.Page.getControl("addRegions").
setVisible(false);
formContext.getControl("addRegions").
setVisible(false);
Show field, “addRegions” Xrm.Page.getControl("addRegions").
setVisible(true);
formContext.getControl("addRegions").
setVisible(true);
Get lookup field “region”, and its properties var regionLookup = Xrm.Page.
getAttribute("region").getValue();
if (regionLookup != null) {
var name = regionLookup[0].name;
var guid = regionLookup[0].

id.slice(1, -1);
var entityType =

regionLookup[0].entityType;
}
var regionLookup = formContext.
getAttribute("region").getValue();
if ( regionLookup != null) {
var name = regionLookup[0].name;
var guid = regionLookup[0].

id.slice(1, -1);
var entityType =

regionLookup[0].entityType;
}
Remove option, 15220000, from ‘showRegions’ option set. Xrm.Page.getControl("showRegions").
removeOption(15220000);
formContext.getControl("showRegions").
removeOption(15220000);
Add option, 15220001 (with text: ‘Africa’), to ‘showRegions’ option set. Xrm.Page.getControl("showRegions").
addOption({
value:15220001,
text:'Africa'});
formContext.getControl("showRegions").
addOption({
value:15220001,
text:'Africa'});
Show tab, with logical name “regionsTab” Xrm.Page.ui.tabs.get("regionsTab").
setVisible(true);
formContext.ui.tabs.get("regionsTab").
setVisible(true);
Hide tab, with logical name “regionsTab” Xrm.Page.ui.tabs.get("regionsTab").
setVisible(false);
formContext.ui.tabs.get("regionsTab").
setVisible(false);
Show section “regionsTab_regSection”, located in tab “regionsTab” Xrm.Page.ui.tabs.get("regionsTab").
sections.get("regionsTab_regSection").
setVisible(true);
formContext.ui.tabs.get("regionsTab").
sections.get("regionsTab_regSection").
setVisible(true);
Hide section “regionsTab_regSection”, located in tab “regionsTab” Xrm.Page.ui.tabs.
get("regionsTab").sections.
get("regionsTab_regSection").
setVisible(false);
formContext.ui.tabs.
get("regionsTab").sections.
get("regionsTab_regSection").
setVisible(false);
Count number of records on sub-grid called “demo-grid” var count = Xrm.Page.
getControl("demo-grid").getGrid().

getTotalRecordCount();
var count = formContext.
getControl("demo-grid").getGrid().
getTotalRecordCount();
Deprecated Client API Replacement Client API Comments
Xrm.Page Forms: ExecutionContext.getFormContext
Commands: Send it as the PrimaryControl parameter
Use of the Xrm.Page object as a static access to the primary form context is still supported to maintain backward compatibility with the existing scripts. Based on the feedback, we understand that the usage of Xrm.Page is high, and it won’t be removed as soon as some other client API methods listed in this section. We encourage you to use the new way of getting form content where possible. More information: Client API form context
Although Xrm.Page is deprecated, parent.Xrm.Page will continue to work in case of HTML web resources embedded in forms as this is the only way to access the form context from the HTML web resource.
Xrm.Page.context Xrm.Utility.getGlobalContext Allows access to the global context without going through the form context.
Xrm.Page.context.getQueryStringParameters formContext.data.attributes The formContext.data.attributes API will make retrieval of non-entity bound data consistent across entity forms, metadata-driven dialogs, and task-based flows. The data will be a combination of custom values sent using the query string and what was specified in the parameters in the openForm method.
Xrm.Page.context.getTimeZoneOffsetMinutes globalContext.userSettings.getTimeZoneOffsetMinutes Moved to globalContext.userSettings
Xrm.Page.context.getUserId globalContext.userSettings.userId Moved to globalContext.userSettings
Xrm.Page.context.getUserLcid globalContext.userSetings.languageId Moved to globalContext.userSettings
Xrm.Page.context.getUserName globalContext.userSettings.userName Moved to globalContext.userSettings
Xrm.Page.context.getUserRoles globalContext.userSettings.securityRoles Moved to globalContext.userSettings
Xrm.Page.context.getIsAutoSaveEnabled globalContext.organizationSettings.isAutoSaveEnabled Moved to globalContext.organizationSettings
Xrm.Page.context.getOrgLcid globalContext.organizationSettings.languageId Moved to globalContext.organizationSettings
Xrm.Page.context.getOrgUniqueName globalContext.organizationSettings.uniqueName Moved to globalContext.organizationSettings
Xrm.Page.data.entity.getDataXml No change in the method, but use “typename” instead of type for lookup attributes.
GridRow.getData GridRow.data GridRow is essentially a form context. This change unifies the interface of GridRow with formContext.
GridRowData.getEntity GridRowData.entity GridRowData is form data. This change unifies the interface of GridRowData with formContextData.
Xrm.Mobile.offline Xrm.WebApi.offline Moved the offline-related methods under Xrm.WebApi.offline
parent.Xrm Use one of the following:

a) Use a custom control created using Power Apps component framework instead of HTML web resources.

b) On forms, use the getContentWindow method of the web resource control.

c) If the getContentWindow method doesn’t work, you can use parent.Xrm to get to the Xrm object inside an HTML web resource. If the HTML web resource is opened in a new window then you should use opener.Xrm instead.

Earlier: An HTML web resource may interact with the Xrm.Page or Xrm.Utility objects within the form by using parent.Xrm.Page or parent.Xrm.Utility.

Now: parent.Xrm.* will work if the HTML web resource is loaded in a form container. It won’t work for HTML web resources that are stand alone, or referenced from the site map or any other places.

NOTEparent.Xrm will be removed after the removal of the ClientGlobalContext.js.aspx page; dates yet to be announced.

addOnKeyPress Use a custom control created using Power Apps component framework
fireOnKeyPress Use a custom control created using Power Apps component framework
removeOnKeyPress Use a custom control created using Power Apps component framework
showAutoComplete Use a custom control created using Power Apps component framework
hideAutoComplete Use a custom control created using Power Apps component framework
Xrm.Utility.alertDialog Xrm.Navigation.openAlertDialog The new signature is consistent with other APIs (openForm) and takes a new set of parameters for flexibility.
Xrm.Utility.confirmDialog Xrm.Navigation.openConfirmDialog The new signature is consistent with other APIs (openForm) and takes a new set of parameters for flexibility.
Xrm.Utility.getBarcodeValue Xrm.Device.getBarcodeValue Moving device-related actions to Xrm.Device
Xrm.Utility.getCurrentPosition Xrm.Device.getCurrentPosition Moving device-related actions to Xrm.Device
Xrm.Utility.isActivityType Xrm.Utility.getEntityMetadata The isActivityType method is synchronous so it was suitable for ribbon rules. However, the replacement method, getEntityMetadata, is asynchronous, and is not suitable for ribbon rules.
Xrm.Utility.openEntityForm Xrm.Navigation.openForm Moving navigation actions to Xrm.Navigation
Xrm.Utility.openQuickCreate Xrm.Navigation.openForm Moving navigation actions to Xrm.Navigation
Xrm.Utility.openWebResource Xrm.Navigation.openWebResource Moving navigation actions to Xrm.Navigation
Note: This API returns VOID in Unified Interface.
globalContext.organizationSettings.baseCurrencyId globalContext.organizationSettings.baseCurrency The replacement method lets you access the display name along with the ID of transaction currency.
globalContext.userSettings.securityRoles globalContext.userSettings.Roles The replacement method lets you access the display name along with the ID of the security roles.
globalContext.userSettings.transactionCurrencyId globalContext.userSettings.transactionCurrency The replacement method lets you access the display name along with the ID of transaction currency.
getData and setData for Silverlight web resources None Silverlight is no longer supported. These methods won’t be available after October, 2020.
formContext.data.entity.save formContext.data.save
ClientGlobalContext.js.aspx None The ClientGlobalContext.js.aspx page is built on the legacy web client infrastructure. As the legacy web client is deprecated and scheduled to be unavailable effective December 1, 2020, the ClientGlobalContext.js.aspx page will also be removed along with the legacy web client on December 1, 2020.
getObject getContentWindow

Reference: https://docs.microsoft.com/en-us/power-platform/important-changes-coming#some-client-apis-are-deprecated

The post Migration from Legacy WebClient to UCI – Deprecated Javascript (Client Api) Collection Book , Replace Deprecated Client API To New and latest Client Api’s appeared first on Microsoft Dynamics 365 Blog.

]]>
4081
Rich Text Editor – HTML Designer for Microsoft dynamics 365 CRM Using JavaScript- NO PCF http://microsoftdynamics.in/2020/07/16/rich-text-editor-html-designer-for-microsoft-dynamics-365-crm-using-javascript-no-pcf/ Thu, 16 Jul 2020 12:38:37 +0000 http://microsoftdynamics.in/?p=3953 one recent requirement needed to have a temporary Rich-text HTML designer for Question Field in KB article and instead of using CK entire js library and using other managed solution we used below HTML Web resource which fulfilled our quick and temporary requirement 

NOTE: The current best practice suggestion is to use PCF control to use PCF.Gallery to get Prebuild PCF control for Rich Text Editor
Step1: Create 2 field - New_Questionhtml and new_questionplain

Step 2: Create an HTML web resource and use above HTML in the source.

step 3: We have not used Parameter and hardcoded HTML field and plain field as below

Step 4: Insert Web resource on form and select web resource created above

Step 5: Save and Publish , our Rich Text HTMl field is ready to use 

The post Rich Text Editor – HTML Designer for Microsoft dynamics 365 CRM Using JavaScript- NO PCF appeared first on Microsoft Dynamics 365 Blog.

]]>

There are lots of posts regarding Creating and HTML designer Rich Text Editor for a field in Microsoft dynamics 365, But almost all of them require some Managed or unmanaged Solution import with lots of JS and HTML web resource.

Below is a simple HTML WebResource which using CKeditor JS.

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/07/Rich-Text-Editor-–-HTML-Designer-for-Microsoft-dynamics-365-CRM-Using-JavaScript-NO-PCF.jpg?fit=1885%2C852

one recent requirement needed to have a temporary Rich-text HTML designer for Question Field in KB article and instead of using CK entire js library and using other managed solution we used below HTML Web resource which fulfilled our quick and temporary requirement

NOTE: The current best practice suggestion is to use PCF control to use PCF.Gallery to get Prebuild PCF control for Rich Text Editor

<html><head><meta><meta><meta></head><body onfocusout="parent.setEmailRange();" style="overflow-wrap: break-word;">

    
        <meta charset="utf-8">
        <meta name="robots" content="noindex, nofollow">
        <title></title>
        <script type="text/javascript" src="../../ClientGlobalContext.js.aspx"></script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
         <!--<script src="../Scripts/new_ckeditor.js" type="text/javascript"></script>-->
       script src="https://cdn.ckeditor.com/4.6.2/standard-all/ckeditor.js"></script>
        <!--<script src="http://cdn.ckeditor.com/4.6.2/basic/ckeditor.js"></script>-->
    
    
        <textarea cols="80" id="editor1" style="width:100%" name="editor1" rows="30"></textarea>
        <textarea id="editor2" name="editor2" style="display: none"></textarea>
        
        <!--Utility Script-->
        <script>
            function entityToHtml(string) {
                for (var i in entity_table) {
                    if (i != 38) {
                        string = string.replace(new RegExp(entity_table[i], "g"), String.fromCharCode(i));
                    }
                }
                //string = string.replace(new RegExp("&#(x?)(\\d+);", "g"), String.fromCharCode(((p1 == 'x') ? parseInt(p2, 16) : p2)));
                string = string.replace(new RegExp("&#(x?)(\\d+);", "g"), function (match, p1, p2, string) {
                    return String.fromCharCode(((p1 == 'x') ? parseInt(p2, 16) : p2));
                });
                string = string.replace(new RegExp(entity_table[38], "g"), String.fromCharCode(38));
                return string;
            }

            var entity_table = {
                // 34: "&quot;",     // Quotation mark. Not required
                38: "&amp;",        // Ampersand. Applied before everything else in the application
                60: "&lt;",     // Less-than sign
                62: "&gt;",     // Greater-than sign
                // 63: "&#63;",      // Question mark
                // 111: "&#111;",        // Latin small letter o
                160: "&nbsp;",      // Non-breaking space
                161: "&iexcl;",     // Inverted exclamation mark
                162: "&cent;",      // Cent sign
                163: "&pound;",     // Pound sign
                164: "&curren;",    // Currency sign
                165: "&yen;",       // Yen sign
                166: "&brvbar;",    // Broken vertical bar
                167: "&sect;",      // Section sign
                168: "&uml;",       // Diaeresis
                169: "&copy;",      // Copyright sign
                170: "&ordf;",      // Feminine ordinal indicator
                171: "&laquo;",     // Left-pointing double angle quotation mark
                172: "&not;",       // Not sign
                173: "&shy;",       // Soft hyphen
                174: "&reg;",       // Registered sign
                175: "&macr;",      // Macron
                176: "&deg;",       // Degree sign
                177: "&plusmn;",    // Plus-minus sign
                178: "&sup2;",      // Superscript two
                179: "&sup3;",      // Superscript three
                180: "&acute;",     // Acute accent
                181: "&micro;",     // Micro sign
                182: "&para;",      // Pilcrow sign
                183: "&middot;",    // Middle dot
                184: "&cedil;",     // Cedilla
                185: "&sup1;",      // Superscript one
                186: "&ordm;",      // Masculine ordinal indicator
                187: "&raquo;",     // Right-pointing double angle quotation mark
                188: "&frac14;",    // Vulgar fraction one-quarter
                189: "&frac12;",    // Vulgar fraction one-half
                190: "&frac34;",    // Vulgar fraction three-quarters
                191: "&iquest;",    // Inverted question mark
                192: "&Agrave;",    // A with grave
                193: "&Aacute;",    // A with acute
                194: "&Acirc;",     // A with circumflex
                195: "&Atilde;",    // A with tilde
                196: "&Auml;",      // A with diaeresis
                197: "&Aring;",     // A with ring above
                198: "&AElig;",     // AE
                199: "&Ccedil;",    // C with cedilla
                200: "&Egrave;",    // E with grave
                201: "&Eacute;",    // E with acute
                202: "&Ecirc;",     // E with circumflex
                203: "&Euml;",      // E with diaeresis
                204: "&Igrave;",    // I with grave
                205: "&Iacute;",    // I with acute
                206: "&Icirc;",     // I with circumflex
                207: "&Iuml;",      // I with diaeresis
                208: "&ETH;",       // Eth
                209: "&Ntilde;",    // N with tilde
                210: "&Ograve;",    // O with grave
                211: "&Oacute;",    // O with acute
                212: "&Ocirc;",     // O with circumflex
                213: "&Otilde;",    // O with tilde
                214: "&Ouml;",      // O with diaeresis
                215: "&times;",     // Multiplication sign
                216: "&Oslash;",    // O with stroke
                217: "&Ugrave;",    // U with grave
                218: "&Uacute;",    // U with acute
                219: "&Ucirc;",     // U with circumflex
                220: "&Uuml;",      // U with diaeresis
                221: "&Yacute;",    // Y with acute
                222: "&THORN;",     // Thorn
                223: "&szlig;",     // Sharp s. Also known as ess-zed
                224: "&agrave;",    // a with grave
                225: "&aacute;",    // a with acute
                226: "&acirc;",     // a with circumflex
                227: "&atilde;",    // a with tilde
                228: "&auml;",      // a with diaeresis
                229: "&aring;",     // a with ring above
                230: "&aelig;",     // ae. Also known as ligature ae
                231: "&ccedil;",    // c with cedilla
                232: "&egrave;",    // e with grave
                233: "&eacute;",    // e with acute
                234: "&ecirc;",     // e with circumflex
                235: "&euml;",      // e with diaeresis
                236: "&igrave;",    // i with grave
                237: "&iacute;",    // i with acute
                238: "&icirc;",     // i with circumflex
                239: "&iuml;",      // i with diaeresis
                240: "&eth;",       // eth
                241: "&ntilde;",    // n with tilde
                242: "&ograve;",    // o with grave
                243: "&oacute;",    // o with acute
                244: "&ocirc;",     // o with circumflex
                245: "&otilde;",    // o with tilde
                246: "&ouml;",      // o with diaeresis
                247: "&divide;",    // Division sign
                248: "&oslash;",    // o with stroke. Also known as o with slash
                249: "&ugrave;",    // u with grave
                250: "&uacute;",    // u with acute
                251: "&ucirc;",     // u with circumflex
                252: "&uuml;",      // u with diaeresis
                253: "&yacute;",    // y with acute
                254: "&thorn;",     // thorn
                255: "&yuml;",      // y with diaeresis
                264: "&#264;",      // Latin capital letter C with circumflex
                265: "&#265;",      // Latin small letter c with circumflex
                338: "&OElig;",     // Latin capital ligature OE
                339: "&oelig;",     // Latin small ligature oe
                352: "&Scaron;",    // Latin capital letter S with caron
                353: "&scaron;",    // Latin small letter s with caron
                372: "&#372;",      // Latin capital letter W with circumflex
                373: "&#373;",      // Latin small letter w with circumflex
                374: "&#374;",      // Latin capital letter Y with circumflex
                375: "&#375;",      // Latin small letter y with circumflex
                376: "&Yuml;",      // Latin capital letter Y with diaeresis
                402: "&fnof;",      // Latin small f with hook, function, florin
                710: "&circ;",      // Modifier letter circumflex accent
                732: "&tilde;",     // Small tilde
                913: "&Alpha;",     // Alpha
                914: "&Beta;",      // Beta
                915: "&Gamma;",     // Gamma
                916: "&Delta;",     // Delta
                917: "&Epsilon;",   // Epsilon
                918: "&Zeta;",      // Zeta
                919: "&Eta;",       // Eta
                920: "&Theta;",     // Theta
                921: "&Iota;",      // Iota
                922: "&Kappa;",     // Kappa
                923: "&Lambda;",    // Lambda
                924: "&Mu;",        // Mu
                925: "&Nu;",        // Nu
                926: "&Xi;",        // Xi
                927: "&Omicron;",   // Omicron
                928: "&Pi;",        // Pi
                929: "&Rho;",       // Rho
                931: "&Sigma;",     // Sigma
                932: "&Tau;",       // Tau
                933: "&Upsilon;",   // Upsilon
                934: "&Phi;",       // Phi
                935: "&Chi;",       // Chi
                936: "&Psi;",       // Psi
                937: "&Omega;",     // Omega
                945: "&alpha;",     // alpha
                946: "&beta;",      // beta
                947: "&gamma;",     // gamma
                948: "&delta;",     // delta
                949: "&epsilon;",   // epsilon
                950: "&zeta;",      // zeta
                951: "&eta;",       // eta
                952: "&theta;",     // theta
                953: "&iota;",      // iota
                954: "&kappa;",     // kappa
                955: "&lambda;",    // lambda
                956: "&mu;",        // mu
                957: "&nu;",        // nu
                958: "&xi;",        // xi
                959: "&omicron;",   // omicron
                960: "&pi;",        // pi
                961: "&rho;",       // rho
                962: "&sigmaf;",    // sigmaf
                963: "&sigma;",     // sigma
                964: "&tau;",       // tau
                965: "&upsilon;",   // upsilon
                966: "&phi;",       // phi
                967: "&chi;",       // chi
                968: "&psi;",       // psi
                969: "&omega;",     // omega
                977: "&thetasym;",  // Theta symbol
                978: "&upsih;",     // Greek upsilon with hook symbol
                982: "&piv;",       // Pi symbol
                8194: "&ensp;",     // En space
                8195: "&emsp;",     // Em space
                8201: "&thinsp;",   // Thin space
                8204: "&zwnj;",     // Zero width non-joiner
                8205: "&zwj;",      // Zero width joiner
                8206: "&lrm;",      // Left-to-right mark
                8207: "&rlm;",      // Right-to-left mark
                8211: "&ndash;",    // En dash
                8212: "&mdash;",    // Em dash
                8216: "&lsquo;",    // Left single quotation mark
                8217: "&rsquo;",    // Right single quotation mark
                8218: "&sbquo;",    // Single low-9 quotation mark
                8220: "&ldquo;",    // Left double quotation mark
                8221: "&rdquo;",    // Right double quotation mark
                8222: "&bdquo;",    // Double low-9 quotation mark
                8224: "&dagger;",   // Dagger
                8225: "&Dagger;",   // Double dagger
                8226: "&bull;",     // Bullet
                8230: "&hellip;",   // Horizontal ellipsis
                8240: "&permil;",   // Per mille sign
                8242: "&prime;",    // Prime
                8243: "&Prime;",    // Double Prime
                8249: "&lsaquo;",   // Single left-pointing angle quotation
                8250: "&rsaquo;",   // Single right-pointing angle quotation
                8254: "&oline;",    // Overline
                8260: "&frasl;",    // Fraction Slash
                8364: "&euro;",     // Euro sign
                8472: "&weierp;",   // Script capital
                8465: "&image;",    // Blackletter capital I
                8476: "&real;",     // Blackletter capital R
                8482: "&trade;",    // Trade mark sign
                8501: "&alefsym;",  // Alef symbol
                8592: "&larr;",     // Leftward arrow
                8593: "&uarr;",     // Upward arrow
                8594: "&rarr;",     // Rightward arrow
                8595: "&darr;",     // Downward arrow
                8596: "&harr;",     // Left right arrow
                8629: "&crarr;",    // Downward arrow with corner leftward. Also known as carriage return
                8656: "&lArr;",     // Leftward double arrow. ISO 10646 does not say that lArr is the same as the 'is implied by' arrow but also does not have any other character for that function. So ? lArr can be used for 'is implied by' as ISOtech suggests
                8657: "&uArr;",     // Upward double arrow
                8658: "&rArr;",     // Rightward double arrow. ISO 10646 does not say this is the 'implies' character but does not have another character with this function so ? rArr can be used for 'implies' as ISOtech suggests
                8659: "&dArr;",     // Downward double arrow
                8660: "&hArr;",     // Left-right double arrow
                // Mathematical Operators
                8704: "&forall;",   // For all
                8706: "&part;",     // Partial differential
                8707: "&exist;",    // There exists
                8709: "&empty;",    // Empty set. Also known as null set and diameter
                8711: "&nabla;",    // Nabla. Also known as backward difference
                8712: "&isin;",     // Element of
                8713: "&notin;",    // Not an element of
                8715: "&ni;",       // Contains as member
                8719: "&prod;",     // N-ary product. Also known as product sign. Prod is not the same character as U+03A0 'greek capital letter pi' though the same glyph might be used for both
                8721: "&sum;",      // N-ary summation. Sum is not the same character as U+03A3 'greek capital letter sigma' though the same glyph might be used for both
                8722: "&minus;",    // Minus sign
                8727: "&lowast;",   // Asterisk operator
                8729: "&#8729;",    // Bullet operator
                8730: "&radic;",    // Square root. Also known as radical sign
                8733: "&prop;",     // Proportional to
                8734: "&infin;",    // Infinity
                8736: "&ang;",      // Angle
                8743: "&and;",      // Logical and. Also known as wedge
                8744: "&or;",       // Logical or. Also known as vee
                8745: "&cap;",      // Intersection. Also known as cap
                8746: "&cup;",      // Union. Also known as cup
                8747: "&int;",      // Integral
                8756: "&there4;",   // Therefore
                8764: "&sim;",      // tilde operator. Also known as varies with and similar to. The tilde operator is not the same character as the tilde, U+007E, although the same glyph might be used to represent both
                8773: "&cong;",     // Approximately equal to
                8776: "&asymp;",    // Almost equal to. Also known as asymptotic to
                8800: "&ne;",       // Not equal to
                8801: "&equiv;",    // Identical to
                8804: "&le;",       // Less-than or equal to
                8805: "&ge;",       // Greater-than or equal to
                8834: "&sub;",      // Subset of
                8835: "&sup;",      // Superset of. Note that nsup, 'not a superset of, U+2283' is not covered by the Symbol font encoding and is not included.
                8836: "&nsub;",     // Not a subset of
                8838: "&sube;",     // Subset of or equal to
                8839: "&supe;",     // Superset of or equal to
                8853: "&oplus;",    // Circled plus. Also known as direct sum
                8855: "&otimes;",   // Circled times. Also known as vector product
                8869: "&perp;",     // Up tack. Also known as orthogonal to and perpendicular
                8901: "&sdot;",     // Dot operator. The dot operator is not the same character as U+00B7 middle dot
                // Miscellaneous Technical
                8968: "&lceil;",    // Left ceiling. Also known as an APL upstile
                8969: "&rceil;",    // Right ceiling
                8970: "&lfloor;",   // left floor. Also known as APL downstile
                8971: "&rfloor;",   // Right floor
                9001: "&lang;",     // Left-pointing angle bracket. Also known as bra. Lang is not the same character as U+003C 'less than'or U+2039 'single left-pointing angle quotation mark'
                9002: "&rang;",     // Right-pointing angle bracket. Also known as ket. Rang is not the same character as U+003E 'greater than' or U+203A 'single right-pointing angle quotation mark'
                // Geometric Shapes
                9642: "&#9642;",    // Black small square
                9643: "&#9643;",    // White small square
                9674: "&loz;",      // Lozenge
                // Miscellaneous Symbols
                9702: "&#9702;",    // White bullet
                9824: "&spades;",   // Black (filled) spade suit
                9827: "&clubs;",    // Black (filled) club suit. Also known as shamrock
                9829: "&hearts;",   // Black (filled) heart suit. Also known as shamrock
                9830: "&diams;"   // Black (filled) diamond suit
            }
        </script>

        <!--Utility Script-->
        <script>
            var protos = document.body.constructor === window.HTMLBodyElement;
            validHTMLTags = /^(?:a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|bgsound|big|blink|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|data|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|isindex|kbd|keygen|label|legend|li|link|listing|main|map|mark|marquee|menu|menuitem|meta|meter|nav|nobr|noframes|noscript|object|ol|optgroup|option|output|p|param|plaintext|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|spacer|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr|xmp)$/i;

            function sanitize(txt) {
                var // This regex normalises anything between quotes
                    normaliseQuotes = /=(["'])(?=[^\1]*[<>])[^\1]*\1/g,
                    normaliseFn = function ($0, q, sym) {
                        return $0.replace(/</g, '&lt;').replace(/>/g, '&gt;');
                    },
                    replaceInvalid = function ($0, tag, off, txt) {
                        var
                            // Is it a valid tag?
                            invalidTag = protos &&
                                document.createElement(tag) instanceof HTMLUnknownElement
                             || !validHTMLTags.test(tag),

                            // Is the tag complete?
                            isComplete = txt.slice(off + 1).search(/^[^<]+>/) > -1;

                        return invalidTag || !isComplete ? '&lt;' + tag : $0;
                    };

                txt = txt.replace(normaliseQuotes, normaliseFn)
                         .replace(/<(\w+)/g, replaceInvalid);

                var tmp = document.createElement("DIV");
                tmp.innerHTML = txt;

                return "textContent" in tmp ? tmp.textContent : tmp.innerHTML;
            }
        </script>

        <script>     
            var _htmlCommentField = "new_question";
            var _plainTextCommentField = "new_questionhtml";

            $(document).ready(function () {
                var qStringCollection = pareseQueryString(window.location.search);

                if (qStringCollection.length > 0) {
                    var param = (($.grep(qStringCollection, function (n, i) { return (n.ParamName == "htmlcommentfield") })));
                    _htmlCommentField = param.length > 0 ? param[0].ParamValue : _htmlCommentField;

                    param = (($.grep(qStringCollection, function (n, i) { return (n.ParamName == "plaintextcommentfield") })));
                    _plainTextCommentField = param.length > 0 ? param[0].ParamValue : _plainTextCommentField;
                }

                // Render CKEditor
                (function () {
                    //alert(CKEDITOR.basePath);
                    var editor2 = CKEDITOR.replace('editor2', {
                        removePlugins: 'sourcearea',
                        removeButtons: 'Source,Save,NewPage,Preview,Print,Templates,Cut,Copy,Paste,PasteFromWord,Redo,Undo,Find,Replace,SelectAll,Scayt,Form,Radio,TextField,Checkbox,Textarea,Select,Button,ImageButton,HiddenField,Bold,Italic,Underline,Strike,Subscript,Superscript,CopyFormatting,RemoveFormat,NumberedList,BulletedList,Indent,Outdent,Blockquote,CreateDiv,JustifyLeft,JustifyCenter,JustifyRight,JustifyBlock,Language,BidiRtl,BidiLtr,Link,Unlink,Anchor,Table,Image,Flash,HorizontalRule,Smiley,SpecialChar,PageBreak,Iframe,Styles,Format,Font,FontSize,TextColor,BGColor,ShowBlocks,Maximize,About',
                        forcePasteAsPlainText: true
                    });

                    var editor1 = CKEDITOR.replace('editor1', {
                        removePlugins: 'sourcearea',
                        removeButtons: 'About',
                        //forcePasteAsPlainText: true
                        height: '250px'
                    });

                    editor1.on('change', function (ev) {                        
                        if ($.trim(window.parent.Xrm.Page.getAttribute(_htmlCommentField).getValue()) != $.trim(editor1.getData())) {
                            editor2.setData(editor1.getData(), function () {
                                window.parent.Xrm.Page.getAttribute(_htmlCommentField).setValue(editor1.getData());
                                window.parent.Xrm.Page.getAttribute(_plainTextCommentField).setValue(sanitize(entityToHtml(editor2.getData())).replace(/\n\s*\n/g, '\n'));//.replace(/<(?:.|\n)*?>/gm, '');
                            });
                        }
                    });

                    editor1.on('instanceReady', function (ev) {
                        if ($.trim(window.parent.Xrm.Page.getAttribute(_htmlCommentField).getValue()) != null)
                            editor1.setData(window.parent.Xrm.Page.getAttribute(_htmlCommentField).getValue());
                    });

                    editor2.on('instanceReady', function (ev) {
                        document.getElementById("cke_editor2").style.visibility = 'hidden';
                        document.getElementById("cke_editor2").style.display = 'none';
                    });
                })();
            });
            
            // Utility Scripts
            function pareseQueryString(data) {
                var queryStringData = decodeURIComponent(data.split("?")[1]).replace("&data=", "&");

                var queryStringArray = queryStringData.split('&');

                var qStringCollection = [];
                for (var count = 0; count < queryStringArray.length; count++) {
                    var paramsArray = queryStringArray[count].split('=');

                    if (paramsArray.length > 0) {
                        var qString = {};
                        qString.ParamName = paramsArray[0].toLowerCase();
                        qString.ParamValue = paramsArray[1];

                        qStringCollection.push(qString);
                    }
                }

                return qStringCollection;
            }
        </script>
    
</body></html>

Step1: Create 2 field – New_Questionhtml and new_questionplain

Step 2: Create an HTML web resource and use the above HTML in the source.

step 3: We have not used Parameter and hard coded HTML field and plain field as below

Step 4: Insert Web resource on form and select web resource created above

Step 5: Save and Publish, our Rich Text HTML field is ready to use

The post Rich Text Editor – HTML Designer for Microsoft dynamics 365 CRM Using JavaScript- NO PCF appeared first on Microsoft Dynamics 365 Blog.

]]>
3953
Execute Microsoft Power Automate from Ribbon using JavaScript – On demand Power automate flow using Javascript – in UCI – Replace RibbonAction.js http://microsoftdynamics.in/2020/07/11/execute-microsoft-power-automate-from-ribbon-using-javascript-on-demand-power-automate-flow-using-javascript-in-uci-replace-ribbonaction-js/ Fri, 10 Jul 2020 21:32:17 +0000 http://microsoftdynamics.in/?p=3896 how to Execute PowerAutomate on click of a button on the contact record

Below is Demonstrated in below part

Create Power automate Flow to receive HTTPS Request from Javascript and send Email 
Register Javascript
Creating a Ribbon Button on Contact Entity and add javascript action to the button Command and pass PrimaryControl

The post Execute Microsoft Power Automate from Ribbon using JavaScript – On demand Power automate flow using Javascript – in UCI – Replace RibbonAction.js appeared first on Microsoft Dynamics 365 Blog.

]]>

Recently we needed to trigger Power Automate flow from Javascript later after reading my friend's Blog (Ajit Patra Link below) we decided to have a Button which will execute power automate flow using JavaScript.

It was presented as On-demand Power Automate flow to System user

Please go through Referred Ajit’s Blog  for more detail, where he explained how to Execute PowerAutomate on click of a button on the Lead record

Below is Demonstrated in below part

  1. Create Power automate Flow to receive HTTPS Request from Javascript and send Email
  2. Register Javascript
  3. Creating a Ribbon Button on Contact Entity and add javascript action to the button Command and pass PrimaryControl
https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/07/Execute-Microsoft-Power-Automate-from-Ribbon-using-JavaScript-–-On-demand-Power-automate-flow-using-Javascript-–-in-UCI-–-Replace-RibbonAction-js1.jpg?fit=2072%2C1564

Step 1 Create Power automate Flow to receive HTTPS Request from Javascript and send Email

We will create Power automate flow with the trigger “When an HTTP request is received” this will provide us an URL which we will use in our js for execution.

Below are the steps Performed

  1. Create An Power Automate flow, with the trigger ” When an HTTP request is received” 

  2. Use Sample payload to generate the schema , this Schema will be used as Parameter when executing Power automate

  3. Schema generated are available in Actions to be used as dynamic Values

  4.  Now copy the Http Post URL from HTTP action, Also Url will only be available once power automate is saved

Step 2 Register Javascript to Execute Https Request from Microsoft dynamics 365

We will create a simple JS web resource and will use below Javascript Provided by Ajit on his blog: Click Here 

  1. Create New Webreource and use blow Js Code
    function executeRequest(executionContext) {   
    var formContext = executionContext.getFormContext();
        var flowUrl = "Http Post URL";
        var input = JSON.stringify({
            "contactid": formContext .data.entity.getId().replace("{", "").replace("}", "")
        });
        var req = new XMLHttpRequest();
        req.open("POST", flowUrl, true);
        req.setRequestHeader('Content-Type', 'application/json');
        req.send(input);
    }
  2. Save the javascript and add it under the entity Contact

Step 3 Creating a Ribbon Button on Contact Entity and add javascript action to the button Command

  1. Create a new Solution and add the entity where the button needs to be added “testcontact”
  2. Now open the ribbon workbench, If ribbon workbench is not installed, Install Ribbon Workbench from here: Click Here 
  3. Once successfully imported, Open the ribbon workbench and select the Solution created in 1st step

  4. Once loaded we will find 3 Ribbon HOME, SUBGRID, and FORM

  5. Now Drag and drop the button to FORM Ribbon

  6. Give Label, Icon, etc. NOTE IN UCI SVG FORMAT IS SUPPORTED
  7. Now Click on Add new command, Rename it and Click on ADD ACTION

  8. Now search Javascript registered in step 2 and mention function name

    function executeRequest(executionContext) {   
    var formContext = executionContext.getFormContext();
        var flowUrl = "Http Post URL";
    ---------------------------------------------
    ---------------------------
    --------------------------------------------
  9. Most important is PrimaryControl should be passed in Parameter

Thanks

The post Execute Microsoft Power Automate from Ribbon using JavaScript – On demand Power automate flow using Javascript – in UCI – Replace RibbonAction.js appeared first on Microsoft Dynamics 365 Blog.

]]>
3896
Refresh SubGrid – Not Working – Issue while refreshing Sub grid using JavaScript -Refresh SubGrid from HTML webresource http://microsoftdynamics.in/2020/07/08/refresh-subgrid-not-working-issue-while-refreshing-sub-grid-using-javascript-refresh-subgrid-from-html-webresource/ Wed, 08 Jul 2020 16:05:34 +0000 http://microsoftdynamics.in/?p=3866 The post Refresh SubGrid – Not Working – Issue while refreshing Sub grid using JavaScript -Refresh SubGrid from HTML webresource appeared first on Microsoft Dynamics 365 Blog.

]]>

With Recent Requirement, we developed a Custom Multiple File uploader on an entity which uploads multiple files in Notes or Attachment (Unsupported for sure),

Once the upload is done we needed Notes Grid or Attachment subgrid to refresh, but as we were running js from HTML Resource, so we followed below code

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/07/img_5f05ec766f06a.png?fit=1497%2C746

There are 2 ways we can use it.

1. Using it from Html Resource where we want to use DOM. ( Unsupported not recommended)

parent.document.getElementById("attachmentsGrid").control.refresh();

2. Using Js from an Iframe, use Parent

parent.Xrm.Page.getControl("attachmentsGrid").refresh();

// Form Context (Recommended)

formContext.getControl(“attachmentsGrid”).refresh();

3. Using Js on the Record Itself

Xrm.Page.getControl("attachmentsGrid").refresh();

// Form Context (Recommended)

formContext.getControl("attachmentsGrid").refresh();
We Might be sometime not Seeing above code working, I would recommend debugging it, but the most common issue might be that Code is rendering Before Form is fully loaded.

We can use the below code, to the first check if the context is not null and if null is found return and try after 1 sec that is 1000ms.

Function test(executionContext)
{
//// Get FormContext
formContext = executionContext.getFormContext();
if(formContext  != null)
{
//// Get Grid Control
Var getSubgrid = formContext.getControl("attachmentsGrid");
////If Grid Control is empty , Return and timeout for 1 sec
if(getSubgrid  == null)
{
 setTimeout(function () { test(executionContext); }, 1000);
     return;
}
//// If control is not null refresh the grid
formContext.getControl("attachmentsGrid").refresh();
}

}

The post Refresh SubGrid – Not Working – Issue while refreshing Sub grid using JavaScript -Refresh SubGrid from HTML webresource appeared first on Microsoft Dynamics 365 Blog.

]]>
3866
Debug Android App in Chrome Dev tool – Microsoft dynamics 365 finance and Operation mobile App Debugging http://microsoftdynamics.in/2020/06/21/debug-android-app-in-chrome-dev-tool-microsoft-dynamics-365-finance-and-operation-mobile-app-debugging/ Sat, 20 Jun 2020 19:49:17 +0000 http://microsoftdynamics.in/?p=3750 We will divide the post among 3 Parts

Install android-debug.apk app on android (Provided by Microsoft and can be downloaded from Github)
Enabling USB Debugging and Developer mode in Android Device 
Connecting to Remote devices (Microsoft dynamics Android app) from Google Chrome Browser which is now available under chrome://inspect/#devices
Adding BreakPoint in JS and even change try CSS change from Element

The post Debug Android App in Chrome Dev tool – Microsoft dynamics 365 finance and Operation mobile App Debugging appeared first on Microsoft Dynamics 365 Blog.

]]>

Recently I was added to an internal project call by my Friend and Collage who thinks I am an expert in UI and JS development I don’t know why but as I am good at troubleshooting so I continued.

So the Agenda was, Dev team was working on Microsoft dynamics 365 Finance and Operations Mobile application and they went able to figure out how to change the JS and CSS of the Application.

Dev team provided some documents and credentials and I started doing my R&D to at least reach the Debugging part and then  JS and CSS would be easy and browsing through the document itself gave information about Debugging but that was not step by step process so thought of Writing it and share the same.

Debugging Microsoft dynamics 365 Finance and Operations Android app on Chrome Browser dev tool (NOOD JS)

We will divide the post among 3 Parts

  1. Install android-debug.apk app on android (Provided by Microsoft and can be downloaded from Github)
  2. Enabling USB Debugging and Developer mode in Android Device
  3. Connecting to Remote devices (Microsoft dynamics Android app) from Google Chrome Browser which is now available under chrome://inspect/#devices
  4. Adding BreakPoint in JS and even change try CSS change from Element

STEP 1: Install android-debug.apk on android Device

Below is the official Developer Sample from Microsoft: https://github.com/Microsoft/Dynamics365-for-Operations-mobile-FleetManagementSamples

  • Navigate to the page and download android-debug.apk

  • Now copy the APK to your Android Device and install, Remember to check install from unknown just temporary
    Settings => Apps and Notification -> Apps Permission -> Spacial app Access

  • And our app is installed successfully  ( Remember debuting will not work on app downloaded from google app) as both functions and looks the same.

STEP 2: Enabling USB Debugging and Developer mode in Android Device

We will enable Developer Mode and USB Debugging from Setting

  • Navigate to Settings -> About Phone -> and tap on Build Number 5 times to enable the developer mode option

  • Now search “Developer option in setting” or Navigate to Settings -> System -> Developer Options and Enable Developer Option and USB debugging options

STEP 3: Connecting to Remote devices (Microsoft dynamics Android app) from Google Chrome Browser which is now available under chrome://inspect/#devices

Now we are all ready to connect USB debugging from Chrome browser

  • Connect Android Device with PC and Open Chrome Browser, Go to Inspect element / Dev tool -> More Tool and remote Device.There we will see an Option saying it has been deprecated and there is a new way to do it

  • So it has been moved to chrome://inspect/#devices , Open the App in android device which is connected to pc with USB  and Copy the same in the Address bar and we will find an app for inspect.

STEP 4: Adding BreakPoint in JS ExpenseMobile.js and even change try CSS change from Element

Clicking on Inspect will bring up screen preview of the android app and all dev tool option will be available for use

  • Let us know Put breakpoint to ExpenseMobile.js (We need to once access expense management to see the js in resource).

  • We can also try CSS change from Element

The post Debug Android App in Chrome Dev tool – Microsoft dynamics 365 finance and Operation mobile App Debugging appeared first on Microsoft Dynamics 365 Blog.

]]>
3750
Xrm.Navigation.navigateTo : Open Html Web-resource or new – existing record form as a Dialog in Dynamics 365 CRM OOB http://microsoftdynamics.in/2020/06/10/xrm-navigation-navigateto-open-html-web-resource-or-new-existing-record-form-as-a-dialog-in-dynamics-365-crm-oob/ Wed, 10 Jun 2020 11:41:10 +0000 http://microsoftdynamics.in/?p=3572 The post Xrm.Navigation.navigateTo : Open Html Web-resource or new – existing record form as a Dialog in Dynamics 365 CRM OOB appeared first on Microsoft Dynamics 365 Blog.

]]>

1. Open an existing contact record within a dialog on change of primary contact
2. Open a new address record on change of primary contact within a dialog
3. Open an HTML web resource within a dialog on the Account form

Every now and then we might have come to a requirement where the customer says I want to edit 2nd entity on the same form he/she has opened or view it (not satisfied with quick view form), recently I found an OOB method but the only limitation is it’s supported in Only Unified UI.

It can perform 3 types of navigation: Entity List, Entity Record or HTML Resource and that is most commonly we use or requires right.

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/06/open-record-in-a-dialog-navigationto-dvmske.png?fit=1220%2C1492

Check1:Open an existing contact record within a dialog on change of primary contact

I have come up with this requirement much time, where the user wants an option to check and change the values of primary contact manually when primary contact is changed and they don’t want to navigate to different form either.

here we will use below JS snippet available on Microsoft Doc (Click here) on change of Primary contact

var pageInput = {
  pageType: "entityrecord",
    entityName: "contact",
    entityId: "4da0e5b9-88df-e311-b8e5-6c3be5a8b200" //replace with actual ID
};
var navigationOptions = {
    target: 2,
    height: {value: 80, unit:"%"},
    width: {value: 70, unit:"%"},
    position: 1
};
function OpenPrimaryContact()
{
debugger;
Xrm.Navigation.navigateTo(pageInput,navigationOptions);
}

On Change of Primary contact, a Dialog appears inside account record

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/06/img_5ee09ceeb0c80.png?fit=1911%2C950

Check2:Open a new address record on change of primary contact within a dialog

The user wants an option to add a new address record each Time primary contact is changed .

here we will use below JS snippet available on Microsoft Doc (Click here) on change of Primary contact

var pageInput = {
  pageType: "entityrecord",
    entityName: "customeraddress"   
};
var navigationOptions = {
    target: 2,
    height: {value: 80, unit:"%"},
    width: {value: 70, unit:"%"},
    position: 1
};
function OnChangePrimaryContact()
{
debugger;
Xrm.Navigation.navigateTo(pageInput,navigationOptions);
}

On Change of Primary contact, a Dialog appears inside account record to create “Customeraddress”

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/06/img_5ee0ac63ba367.png?fit=1920%2C979

Check3:Open an HTML web resource within a dialog on the Account form

here we will use below JS snippet available on Microsoft Doc (Click here) on change of Primary contact

var pageInput = {
  pageType: "webresource",
    entityName: "dvm_htmlwebresource.html"   
};
var navigationOptions = {
    target: 2,
    height: {value: 80, unit:"%"},
    width: {value: 70, unit:"%"},
    position: 1
};
function OnChangePrimaryContact()
{
debugger;
Xrm.Navigation.navigateTo(pageInput,navigationOptions);
}

On Change of Primary contact, a Dialog appears inside account record with HTML resource

https://i0.wp.com/microsoftdynamics.in/wp-content/uploads/2020/06/img_5ee0c0fb4e32e.png?fit=1920%2C979

CLICK HERECheck more Checkout the OOB method of XRM.Navigation

openAlertDialog
openConfirmDialog
openErrorDialog
openFile
openForm
openUrl
openWebResourc

The post Xrm.Navigation.navigateTo : Open Html Web-resource or new – existing record form as a Dialog in Dynamics 365 CRM OOB appeared first on Microsoft Dynamics 365 Blog.

]]>
3572