Sunday, December 2, 2018

Customizing D365 forms using JavaScript

I know, a lot of people have written about customizing CRM forms with JavaScript, but I am learning some cool stuff and wanted to share what I learned this week.
The big news for me was that Promises are supported in D365 forms now. I am sure this is not news to many people, and to others they have no idea what I am talking about, so this article is for them.
Why are Promises important?
If you have written a JavaScript function that uses a “call back” (passing a function name as a parameter into another function), then you have probably run into the fact that the call back can happen at any time. If you have several of them that need to be run in a sequence, they will sometimes cause your code to fail because it does not execute them synchronously.
I have seen many programmers try to solve this problem by building “Christmas tree” code that nests one function inside the other until you are 15 levels deep in brackets, and lord help you if you if there is a syntax error with one bracket out of place. Even worse is the difficulty to test and maintain all permutations of “Christmas tree” code so that you are sure there are no errors. Promises are an excellent solution to that problem.
A Promise design pattern is way to write a function that will leverage the asynchronous nature of JavaScript with the ability to sequentially perform a series of tasks. 
I learned about Promises from a Pluralsight course authored by Jonathan Mills called JavaScript Best Practices. I did some research and found a few code samples in GitHub for CRM projects that used Promises. Here are some links that I used to learn more, but frankly, some of it was deeper than I needed.
Promises
https://blogs.msdn.microsoft.com/ie/2011/09/11/asynchronous-programming-in-javascript-with-promises/
Promise API framework for CRM
https://code.msdn.microsoft.com/CRM-Web-API-Functions-and-87cd0b45#content
It uses https://github.com/stefanpenner/es6-promise
https://github.com/mariusso/WebAPI.REST.js/releases




Some of the above links say that you need to include the e6promise.js library, and that may have been necessary in earlier versions of CRM, but I am working in V9.1 and it is not necessary to add any other framework to your project, but it did help me understand what is going on.
What got me started on this article was when I needed to build a customization and realized that I needed several sequential calls to fetch data first, then create new records, but they had to be executed in order.
I noticed that Jason Lattimer’s CRM REST Builder used a Promise syntax when I used the Xrm.WebApi option to build a request for fetching data, so I decided to see if I could make that work for me. Besides, I like the succinct format of WebAPI over the XMLHTTP format.
I created a form script called Library.js and in following best practices, created a FormLib namespace so all my methods and properties are prefixed with “FormLib.”.
First I used CRM REST Builder to create an asynchronous call to get some data for me that looks like this:
Xrm.WebApi.online.retrieveMultipleRecords("tn_changeorder", "?$select=tn_changeorderid&$filter=statuscode eq 0 and  _tn_quoteid_value eq <giud>").then(
     function success(results) {
         for (var i = 0; i < results.entities.length; i++) {
             var tn_changeorderid = results.entities[i]["tn_changeorderid"];
         }
     },
     function(error) {
         Xrm.Utility.alertDialog(error.message);
     }
);
Notice the “then” that follows the async call – this was my clue that the Xrm.WebApi was a Promise.
Following Jonathan Mills instructions, I created a wrapper function :
FormLib.GetChangeOrder = function () {
     return new Promise(function (fulfill, reject) {
         // begin REST code

        // end REST code
     });
};
and then I inserted the “fulfill” and “reject” into the REST code, and put it all together so that now my code looks like this:
FormLib.GetChangeOrder = function () {
     return new Promise(function (fulfill, reject) {
         // begin REST code
         Xrm.WebApi.online.retrieveMultipleRecords("tn_changeorder", "?$select=tn_changeorderid&$filter=statuscode eq 0 and  _tn_quoteid_value eq  <guid>" ).then(
             function success(results) {
                 for (var i = 0; i < results.entities.length; i++) {
                     var tn_changeorderid = results.entities[i]["tn_changeorderid"];
                 }
                fulfill();
             },
             function (error) {
                 Xrm.Utility.alertDialog(error.message);
                 reject();
             }
         );
         // end REST code
     });
};

Now every time I make an async call, I create one of these functions (above) and can fire them sequentially using a syntax that looks like this:
FormLib.GetChangeOrder()
            .then(FormLib.CreateRelatedCase)
            .then(FormLib.SetupDetails)
The magic is the fulfill() that calls the next item in the “then-chain”. The reject() allows you to call an error handler and gracefully exit the chain. In my example above, the “.then(FormLib.CreateRelatedCase)” is passed into GetChangeOrder() and executed after it has completed its task of looking for an existing record.
You could argue that it is easier to just call the next function in the chain by using the specific function name instead of calling fulfill(), but then you would have tight coupling and it is difficult to maintain when you have to decipher the code to figure out what the chain is.
Promises solves the problem of deep nesting of functions by splitting them all out to discrete, re-useable, loosely coupled, and testable functions that can be called sequentially. The Promise Design Pattern also makes handling errors and parallel tasks easier to manage. I recommend you learn this design pattern if you are going to do any amount of JavaScript coding.