Archive
Code Snippet | JScript | Capture BPF Stage Parameters
Below is code snippet to capture the BPF stage parameters up on the ‘Stage’ change using jscript.
function onload(executionContext) {
var formContext = executionContext.getFormContext();
// Register event handler on Process Stage Change
formContext.data.process.addOnStageChange(onStageChange);
}
function onStageChange(executionContext) {
var formContext = executionContext.getFormContext();
var stage = formContext.data.process.getSelectedStage();
// Get Stage Name
var currStageName = stage.getName();
// Show Stage Name
Xrm.Navigation.openAlertDialog({ text: "Current StageName - " + currStageName });
// Get Stage ID
var stageID = stage.getID();
// Get Entity Name
var stageEntityName = stage.getEntityName();
// Get Stage Status
var stageStatus = stage.getStatus();
}
- Save this script as web resource and register both the ‘onload’ and ‘onStageChane’ functions on form’s onload event.
- Below is the example of script on Opportunity form.
š
[Step by Step] Using TypeScript in Dynamics 365 9.x
What is TypeScript:
- TypeScript extends JavaScript by adding types to the language. TypeScript sits as a layer on-top of JavaScript, this layer is the TypeScript type system.
- In a layman terms, TypeScript allows C# way of writing jScript.
In this article, lets see how to leverage TypeScript capability while writing client scripts in Dynamics 365.
Key Notes:
- TypeScript’s file extension is ‘.ts‘.
- Dynamics 365 cannot understand TypeScript, it only understands jScript (i.e., .js)
- So we write the script in TypeScript, and use ‘Transpile’ technique to convert TypeScript to jScript.
- Transpiling is taking source code written in one language and transforming into another language. In our case its from .ts to .js
- Don’t worry about Transpiling as Visual Studio will take care of this.
Now we know the basics of TypeScript, lets get started.
Setting up project in Visual Studio:
- Create a new Web Site project in Visual Studio.
- As we are going to Transpile TypeScript files to jScript files, create a new folders ‘ts’ and ‘js’ for code manageability.
- ‘ts’ folder is where we write the TypeScript, ‘js’ folder is where the transpiled jScript resides.
- Next, to transpile TypeScript to jScript, add a new json file with name ‘tsconfig.json‘.
- Paste following statements and save.
{
“compileOnSave”: true,
“compilerOptions”: {
“outDir”: “js”,
“target”: “es5”,
“sourceMap”: true
},
“include”: [
“./ts/**/*”
]
}
- Your ‘tsconfig.json’ should look like below.
- If you observe the ‘tsconfig.json’ statements, they state that whenever you save ‘.ts’ file compile (i.e., compileOnSave’) and save the transpiled ‘.js’ file under ‘js’ folder (i.e., outDir).
- Next, lets install the ‘xrm’ npm package for intellisence to your project. Refer this article for more details.
- Run ‘–save @types/xrm‘ command.
- You would see a new folder ‘node_modules’ with ‘index.d.ts’ file.
- If you are wondering what is ‘index.d.ts’, ‘*.d.ts’ files are used to provide typescript ‘Type’ information.
Write your first TypeScript file:
Now that we got the project setup, lets write a simple ‘TypeScript’ file with ‘onload’ function on ‘Contact’ entity.
- Add a new file ‘contact.ts’ under ‘ts’ folder.
- Lets adding following basic structure contains ‘interface’ and ‘onload’ function.
- A namespace is a way that is used forĀ logical grouping of functionalities. It allows us to organize our code in a much cleaner way.
- Now, lets extend the onload function by reading Contact Name from ‘name’ field and popup.
- Lets extend further by registering ‘onchange’ event on ‘Contact Name’ field.
- Save the ‘contact.ts’ file and you would get transpiled ‘contact.js’ jScript file under ‘js’ folder.
- Following the TypeScript code if you want to use.
namespace Pract {
export function onload(executionContext: Xrm.Events.EventContext) {
let formContext = executionContext.getFormContext();// Define ‘String Attribute’ variable to read Contact Name Attribute
let attrContactName: Xrm.Attributes.StringAttribute;
attrContactName = formContext.getAttribute<Xrm.Attributes.StringAttribute>(“firstname”);// Register onchange event
attrContactName.addOnChange(this.contactName_onchange);// Read Attribute Value
let contactName = attrContactName.getValue();var alertStrings = { confirmButtonLabel: “Yes”, text: contactName, title: “Onload Event” };
var alertOptions = { height: 120, width: 260 };
Xrm.Navigation.openAlertDialog(alertStrings, alertOptions).then(
function success(result) {
console.log(“Alert dialog closed”);
},
function (error) {
console.log(error.message);
}
);
}function contactName_onchange(executionContext: Xrm.Events.EventContext) {
alert(“OnChange triggered!”);
}
}
Register and test the script:
- Add the transpiled ‘contact.js’ file as web resource to Dynamics application.
- On ‘Contact’ form register the ‘onload’ event. Convention should be ‘namespace.functionname’ (i.e.,Pract.onload).
- Open the ‘Contact’ record and you would get the ‘Name’ value as pop-up.
š
HTML & JScript – Read and Encode file
We got a requirement in ADX portal, to read and convert the file content to Base64String , which eventually will be submitted to an external API.
Below is the code snippet to read the File content, browsed using the HTML ‘File Upload’ control:
function readFileAsText(){
try {
// Read the browsed file from ‘File Upload’ control.
var fileToLoad = document.getElementById(“fileOE“).files[0];var fileReader = new FileReader();
fileReader.onload = function (fileLoadedEvent) {
// Set the file content to variable
var textFromFileLoaded = fileLoadedEvent.target.result;
alert(“File Content – ” + textFromFileLoaded);// Using ‘window.btoa’ encode the plain text to Base 64
var convertedString = window.btoa(unescape(encodeURIComponent(textFromFileLoaded)));
alert(“Base 64 content – ” + convertedString);
};fileReader.readAsText(fileToLoad, “UTF-8”);
} catch (e) {
alert(“Error in readFileAsText(); Error – ” + e.description);
}
}<body>
<label for=”fileOE”>Pick the file </label><br>
<input type=”file” id=”fileOE” />
<input type=”button” value=”Upload” onclick=”readFileAsText()” />
</body>
- Execute the code and you will get output as below

File content as text

Encoded File Content (Base 64)
š
D365 – Multi Select Option set JScript Syntax
In this article I am going to provide JScript syntax’s to use in projects.
Refer my previous article on configuringĀ Multi Select Option set fields.
// Read the values
var branches = Xrm.Page.getAttribute(“new_branches”).getValue();
Xrm.Utility.alertDialog(“Branches – ” + branches, null);// Set the values (i.e., Hyderabad,Chennai)
Xrm.Page.getAttribute(“new_branches”).setValue([100000000, 100000001]);// Determine if the option is selected
// Non-IE Browser
var isCitySelected = Xrm.Page.getAttribute(“new_branches”).getValue().includes(100000000);// IE Browser
var isCitySelected = Xrm.Page.getAttribute(“new_branches”).getValue().indexOf(100000000)>=0;
Xrm.Utility.alertDialog(“Is City Selected – ” + isCitySelected, null);
// Clear the values
Xrm.Page.getAttribute(“new_branches”).setValue(null);
Create a web resource with these syntax’s and map to the form.
š
Build Auto Complete Text Box using Jscript ā CRM 2016
In CRM 2016, we got showAutoComplete and hideAutoComplete methods to configure the auto-completion experience in text controls in forms.
In this article, I am going to configureĀ āAuto Completeā feature forĀ my āLocalityā text box on my Account form.
JScript:
function suggestLocality() {
// List of sample Locality names to suggest
accounts = [
{ name: ‘AA Street’, code: ‘A01’ },
{ name: ‘AB Street’, code: ‘A02’ },
{ name: ‘AC Street’, code: ‘A03’ },
{ name: ‘Benetten street’, code: ‘A04’ },
{ name: ‘Beverly Hills’, code: ‘A05’ },
{ name: ‘City Street’, code: ‘A06’ },
{ name: ‘City Power & Light’, code: ‘A07’ },
{ name: ‘Aruna Street’, code: ‘A08’ },
{ name: ‘Winery Street’, code: ‘A09’ },
{ name: ‘Coho Vineyard & Winery’, code: ‘A10’ },
{ name: ‘Zeebra Street.’, code: ‘A11’ }
];var localityKeyPress = function (ext) {
try {
var userInput = Xrm.Page.getControl(“raj_locality”).getValue();
resultSet = {
results: new Array(),
commands: {
id: “sp_commands”,
label: “Explore CRM”, // Help link text
action: function () {
window.open(“http://rajeevpentyala.com”); // Help link URL
}
}
};// Read the ‘Text’ entered in Locality field.
var userInputLowerCase = userInput.toLowerCase();
for (i = 0; i < localities.length; i++) {
if (userInputLowerCase === localities[i].name.substring(0, userInputLowerCase.length).toLowerCase()) {
resultSet.results.push({
id: i,
fields: [accounts[i].name]
//, icon:<url> — Its an option field. You can show icon next to the Auto populated text.
});
}
if (resultSet.results.length >= 10) break;
}if (resultSet.results.length > 0) {
// If matches found; Show the Auto complete text area with matched localitites (i.e., Up to 10)
ext.getEventSource().showAutoComplete(resultSet);
} else {
// If no match found; Hide the Auto complete text area.
ext.getEventSource().hideAutoComplete();
}
} catch (e) {
alert(“Error while auto complete – ” + e.description);
}
};// Attach Key Press event to ‘Locality’ text box
Xrm.Page.getControl(“raj_locality”).addOnKeyPress(localityKeyPress);
}
How do I use it:
- Copy the āsuggestLocalityā function and create a web resource in CRM.
- Register the āsuggestLocalityā function on onload event of Account form.
- Publish the Customization’s.
- Open an Account and start typing in “Locality” text box.
- You can extend the script by instead of hard coding Localities, you can read from any existing entity and populate the list.
Important Notes on Auto Complete feature:
- āAuto Completeā show up to 10 matching strings in a drop-down list as users press keys to type character in a specific text field.
- These methods arenāt supported for the CRM mobile clients (phones or tablets).
š
Script error with navigate() statement while navigate between forms ā CRM Jscript
We have a Custom entity with 3 forms and the requirement is to navigate to a different form based on a field value .
So we registered a script on form āloadā event to navigate to a specific form based on an option set value.
Navigation worked as expected except few userās that too when application should take User to āForm 2ā.
Reason and Fix
- We configured new Security Roles recently.
- Our forms were role based and we missed enabling newly added āSecurity Roleā for āForm 2ā.
- By enabling newly added Security Role for āForm 2ā script started working.
š
CRM 2015 – Useful JScript Snippets and Syntaxes
Below are the list of useful scripts and syntax’s
Filter look up records
Letās consider a scenario, āPrimary Contactā lookup on Account form shouldĀ display only Contacts with āBusiness Phoneā (i.e., Contact.telephone1 != Null)
Steps :
- Add PreSearch event for āPrimary Contactā lookup
- In the event handler define Filter and set to the lookup using āaddCustomFilterā method
Script:
// Attach below ‘onload’ function to Form onload event
function onload() {
Xrm.Page.getControl(“primarycontactid”).addPreSearch(filterCustomerContacts);
}
function filterCustomerContacts() {
//Only show Contacts with ‘Business Phone’
var primaryContactFilter = “<filter type=’and’><condition attribute=’telephone1′ operator=’not-null’ /></filter>”;
Xrm.Page.getControl(“primarycontactid”).addCustomFilter(primaryContactFilter, “contact”);
}
Get fields of specific types
One of my blog follower asked this question “How to get list of all Option Set fields placed on the form?”.
Below is the Script to get Attributes based on Type or Requirement Level using “Xrm.Page.data.entity.attributes.forEach”
Script:
function onload() {
var requiredAttributeNames = [];
var optionsetAttributeNames = [];
Xrm.Page.data.entity.attributes.forEach(
function (attribute, index) {
if (attribute.getRequiredLevel() == “required”) {
requiredAttributeNames.push(attribute.getName());
}
if (attribute.getAttributeType() == “optionset”) {
optionsetAttributeNames.push(attribute.getName());
}
});
alert(“Required Attributes on the form are : ” + requiredAttributeNames.join());
alert(“Attributes of Type Optionset on the form are : ” + optionsetAttributeNames.join());
}
Callback functions on Save
Saves the record asynchronously with the option to set callback functions to be executed after the save operation is completed.
Script
Xrm.Page.data.save().then(successCallback, errorCallback);
successCallback() {
alert(“Form saved !!!”);
}
function errorCallback(saveErrorResponse) {
if (saveErrorResponse != null) {
if (saveErrorResponse.message != ‘undefined’ && saveErrorResponse.message != null) {
alert(“Error on Save – ” + saveErrorResponse.message);
}
}
}
Get control placed on Header
- var nameControlInHeader = Xrm.Page.getControl(“header_{fieldname}”);
Get control placed in business process flow
- var nameControlInBPF = Xrm.Page.getControl(“header_process_{fieldname}”);
- We can get controls in the active stage.
Hide\Show time portion of Date Control
- Page.getControl(“createdon”).setShowTime(true/false);
Syntaxes
- getUserPrivilege ā When field level security has been applied to an attribute, determine whether a user has privileges to perform create, read, or update operations on the attribute
Xrm.Page.getAttribute(“name”).getUserPrivilege().canUpdate;
- getMin – Get the minimum allowed value for an attribute that contains a number
Xrm.Page.getAttribute(“creditlimit”).getMin()
- getMax – Get the maximum allowed value for an attribute that contains a number
Xrm.Page.getAttribute(“creditlimit”).getMax()
- getIsPartyList – Determines whether an attribute is a partylist.
Xrm.Page.getAttribute(“to”).getIsPartyList()
- getAttributeType – Get the type of attribute (i.e., Option set,Text etcā¦)
Xrm.Page.getAttribute(0).getAttributeType()
- getFormat- Get attributeās format. (i.e., Text,URL,Email etcā¦)
Xrm.Page.getAttribute(0).getFormat()
- getInitialValue – Get the initial value of a Boolean or Optionset attribute
Xrm.Page.getAttribute(“address1_addresstypecode”).getInitialValue()
- getMaxLength – Get the maximum allowed length for an attribute that contains a string
Xrm.Page.getAttribute(“name”).getMaxLength()
- alertDialog – Display a non-blocking alert dialog with a callback function.
var alertDisplayed = false;
Xrm.Utility.alertDialog(
“Showing Alert”,
function () { alertDisplayed = true; }
)
- confirmDialog ā Display a Non-blocking Confirm dialog with different callbacks depending on the button clicked by the user.
var agree = false;
Xrm.Utility.confirmDialog(
“Do you agree?”,
function () { agree = true;},
function () { agree = false; }
);
š
Exclude namespaces from XML using Jscript
In one of my requirement I had to parse XML and find node values.
Ā My XML looks as below
<NS1:Envelope xmlns:NS1=“http://schemas.xmlsoap.org/soap/envelope/“>
<QueryBalanceResult>
<NS1:AvailableCredit>17400</NS1:AvailableCredit>
</QueryBalanceResult>
</NS1:Envelope>
Since the XML has got namespaces I need to exclude namespaces before I find the node.Ā
Below is the logic to exclude namespaces
var xmlWithNamespaces={Your xml with namespaces};
var xmlWithNoNamespaces= xmlWithNamespaces.replace(/<(\/?)([^:>\s]*:)?([^>]+)>/g, “<$1$3>”);
š
Identify āAuto Saveā in JScript onload & onsave events ā CRM 2013
CRM 2013 has got a new āAuto Saveā feature which periodically saves the form after new data entered.
Problem with frequent auto save
- The problem with this design is whenever auto-saveĀ fires, itĀ causesĀ unwanted execution of the registered onload & onsave events.
To identify āAuto Saveā event in āonload & onsaveā below is useful approach
On SaveĀ
- Check Ā the āSave Modeā of āEvent Argsā, If Save Mode is ā70ā then save event is caused by āAuto Saveā
- Make sure to check ‘Pass execution context as first parameter’ while registering ‘onsave’ event
function onsave(eventArgs) {
var saveMode = eventArgs.getEventArgs().getSaveMode();
// 70 ā AutoSave
if (saveMode == 70) {
alert(āSave caused by AutoSaveā);
// By setting Form dirty, we will make sure the traditional save event executes when you click on āSaveā button
Xrm.Page.data.setFormDirty(true);
}
else {
alert(āTraditional Save eventā);
}
}
Note –
- Since the āAutoSaveā periodically saves the form data, youĀ might notĀ get traditional āonsaveā event fired.
- If you want your logic to be executed in traditional āonsaveā event, set form dirty to ātrueā in āAutoSaveā save mode.
On LoadĀ
āonloadā event caused by āAutoSaveā does not clears the global variables. So use below steps to check āAutoSaveā event on āonloadā
- Declare and set a global variable
- Check the variable on onload event
var formLoaded = false;
function onload() {
if (!formLoaded) {
alert(“Traditional form load happend !!!”);
}
formLoaded = true;
}
- Above function the ‘If’ block executes onlyĀ first time when you open the form
š
Xrm.Utility is undefined error – CRM 2011
Other day when I deployed my solution on a new CRM server, I was getting āXrm.Utility is undefinedā script error.
I referedāXrm.Utilityā JScriptin my code to open forms which was causing script issue.
Reason & Fix
- The CRM server is not having UR 8
- Since Xrm.Utility object was added in CRM 2011 Update Rollup 8, installing UR 8 on server solved the issue
š