Blog, Development

Microsoft Dynamics 365 v9.0: What’s new in clientside for devs besides Xrm.WebApi

After analysis of new namespaces and methods that were released as a part of new 9.0 version I come to conclusion that “Dynamics 365  CE” Product Team actively works on elimination of gap between methods that are available to Product Team and usual developers. And here is why:

Xrm.Utility.lookupObjects

The first and very useful new feature is new Xrm.Utility.lookupObjects method. I (like many other developers) before this release used unsupported approach similar to this or developed own dialogs to support “record selection” scenarios. Luckily it’s not needed anymore because now we have supported api that allows to use Lookup form dialog in form/grid scripts and Html/Js webresources. Here is an example of usage:

var lookupOptions = {
	defaultEntityType: "account",
	entityTypes: ["account", "contact"],
        allowMultiSelect: true
};

Xrm.Utility.lookupObjects(lookupOptions)
	.then(function(result){
		if (result == null || result.length == 0) {
			console.log("No records selected");
		} else {
			console.log(result.length + " records were selected");
			for(var i = 0; i < result.length; i++){
				console.log("Selected Record " + i + " id " + result[i].id + " entityType " + result[i].typename);
			}
		}
	})
	.fail(function(error){
		console.log("Error during opening lookup -" + error);
	});

Provided code opens lookup dialog with 2 allowed for selection entities (accounts and contacts) with account selected by default with possibility to choose one or several records. Full description of method and all available parameters you can find in documentation. Code in action:

Xrm.Utility.showProcessIndicator/Xrm.Utility.closeProcessIndicator

I believe many developers created own way to lock record form/grid during execution on long running operations to avoid user actions. Here is one of possible implementations that uses jQuery (personally I used similar approach). Now we have neat and supported way of doing it – pair of Xrm.Utility.showProcessIndicator/Xrm.Utility.closeProcessIndicator methods. Here is example of usage (instead of long-running operation I used setTimeout to explain approach used):

Xrm.Utility.showProgressIndicator("Background Operation");
console.log(new Date() + " window is shown");

setTimeout(function(){
	Xrm.Utility.closeProgressIndicator();
	console.log(new Date() + " window is closed");
}, 5000);

Code in action:

Xrm.Navigation

Xrm.Navigation is brand new namespace that contains both previously known (openAlertDialog, openConfirmDialog, openWebResource, openForm) and new methods (openErrorDialog, openUrl).

Usage and screenshots of openAlertDialog and openConfirmDialog:

var alertStrings = {
	confirmButtonLabel: "Sure!",
	text: "My Message Text"
};

Xrm.Navigation.openAlertDialog(alertStrings).then(
	function(){
		console.log("Dialog was closed");
	},
	function(){
		console.log("Something went wrong");
	});

var confirmStrings = {
	cancelButtonLabel: "No Way!",
	confirmButtonLabel: "Sure!",
	subtitle: "Really?",
	title: "If you are sure click 'Sure!"
};

Xrm.Navigation.openConfirmDialog(confirmStrings).then(
	function(result){
		console.log("Dialog was closed with result - " + !!result.confirmed);
	},
	function(){
		console.log("Something went wrong");
	});

There are 2 things to notice – developer has got full control over all labels (yes, even over buttons!) and re-flavoring of layout.

New openErrorDialog method allows to show standard “Ooops, I did it again Something went wrong” dialog. Great thing that based on your scenario you can provide possibility not only notify user of error but provide additional log information for download. Here are script and demonstration:

var errorOptions = {
	details: "You can enter log for download here",
	message: "Error"
};

Xrm.Navigation.openErrorDialog(errorOptions).then(
	function(){
		console.log("Dialog was closed");
	},
	function(){
		console.log("Something went wrong");
	});

Another cool method that became available for developers is openFile. Usecase for it is following – imagine that based on some scenario you have need to provide user possibility to download file. Here is the code and demonstration:

var file = {
	fileContent: "Q29udGVudCBvZiBmaWxlIGhlcmU=",
	fileName: "FileName.txt",
	mimeType: "text/rtf"
};

Xrm.Navigation.openFile(file).then(
	function(){
		console.log("Dialog was closed");
	},
	function(){
		console.log("Something went wrong");
	});

Small note – file content has to be provided in Base 64 encoded format.

Xrm.Utility

During my R&D I discovered that Xrm.Utility got one new method – openDialog. My first thought that this method can be used to open Dialogs but when I look on it closer I realized that it is wrapper on top of Xrm.Internal.openDialog – method that made possible to open your Html/Js WebResources in “standard way”. No more words here is code that demonstrates how to use method:

var dialogUrl = "/WebResources/extreme_/eXtremeDemoDialog.html?id=" + Xrm.Page.data.entity.getId() + "&typename=" + Xrm.Page.data.entity.getEntityName();

var dialogOptions = {
	height: 500,
	width: 500
};

var dialogArguments = {
	stringParameter: "String Value",
	intParameter: 1
};

Xrm.Utility.openDialog(dialogUrl, dialogOptions, dialogArguments, null, function(result){
	console.log("Dialog Closed");
	for(var i in result){
		console.log("result." + i + " is equal to " + result[i]);
	}
});

Description of expected parameters:

dialogUrl – prepared Url of your webresource to be shown.

dialogOptions – special object that contains 2 properties – height and width that defines size of dialog window shown.

dialogArguments – additional object that you can use to pass parameters inside dialog window. Here is how you can use it inside dialog’s code:

var dialogArgumets = getDialogArguments();

Fourth parameter is ‘initFunctionName’. I haven’t found usage for it so I left it blank.

Last fifth parameter is callback function that is called when dialog is closed.

This method is not documented so there is a high chance that usage of this method can be considered as unsupported customization. Also this method is available in “Web Client” and not available in new UUI.

10 Comments

  1. Hi Andrii,

    Is it possible to pass parameter for filtering (or addCustomFilter) the Xrm.Utility.lookupObjects ?

    Thanks

  2. I suspect Xrm.Internal.openDialog is a dead end destined to disappear as the next set of user interface changes are made.

    1. Ben,
      Let’s assume that you are right (I’m not saying you are not) then can you explain why MS spend time adding another one wrapper on top of Xrm.Internal.openDialog and added openDialog method to Xrm.Utility namespace and migrated a lot of clientside code to use Xrm.Utility.openDialog instead of Xrm.Internal.openDialog? I’m crossing my fingers that my assumption is correct (that is absolutely opposite to yours) – that openDialog will become supported method in both interfaces.

      1. Hi Andrew,
        Xrm.Utility.openDialog has been working fine in 8.2 and 2016 at least (maybe even earlier)
        Good to know that it still alive in 9.0 🙂
        Thanks for the great overview as always!

        1. Just checked environments I have access to and it seems that this method is around at least since 8.1. Good to know. Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.