From Basics to Brilliance: TypeScript Examples for Model Driven Apps

This is the last of a blogpost series on how to apply TypeScript in Model Driven Apps, In my previous blogpost I’ve explained how to create a TypeScript project in Visual Studio for Model Driven Apps, in this blogpost I will show you some basic examples but also other 3 cool examples in order to open a Custom Page, call Custom API and call a Clow Flow.

The idea is you can re-use this code in your projects and of course changing it a bit according to your requirements.

Without further introduction let’s begin.

Basic examples

I have already lost count of the times I have had to apply some basic logic in main forms, and when I say basic logic I mean that depending on certain conditions I have to make some fields mandatory or not, or depending on these conditions I have to hide or show a field.

Or it could even be retrieving a related record and setting a search field with the retrieved related record, well these are very common scenarios in projects. Having said that just to give you some context this code applies to the main form of the account.

The following code is divided into sections, the first part is to show how to retrieve the value of different columns where the data type is different like string, number, option set, lookup, date.

In the second part I am using Dataverse web API to retrieve a single record in this case I am retrieving an account with its name and its main contact which is a lookup field. Then I am setting the primary contact field with the search contact of the retrieved account.

And finally in the third part I am making one field required and making another field hidden:

const formcontext = executionContext.getFormContext();
 
 //retrieve values from the form
 const exampleLookup: Xrm.Attributes.LookupAttribute = formcontext.getAttribute<Xrm.Attributes.LookupAttribute>(‘primarycontactid’);
 const exampleString = formcontext.getAttribute<Xrm.Attributes.StringAttribute>(‘websiteurl’).getValue();
 const exampleDateTime = formcontext.getAttribute<Xrm.Attributes.DateAttribute>(‘column_schema_name’).getValue();
 const exampleOptionset = formcontext.getAttribute<Xrm.Attributes.OptionSetAttribute>(‘industrycode’).getValue();
 const numberOfEmpAtt = formcontext.getAttribute<Xrm.Attributes.NumberAttribute>(‘numberofemployees’);
 
//retrieve the record GUID
 const recordId = formcontext.data.entity.getId();
 //use the Web API to retrieve a single record
 const accountData = await Xrm.WebApi.retrieveRecord(‘account’, recordId, ‘?$select=name,_primarycontactid_value’);
 const contactId = accountData[‘_primarycontactid_value’];
 const contactName = accountData[‘_primarycontactid_value@OData.Community.Display.V1.FormattedValue’];
 //create a lookup object
 const lookupData: Xrm.LookupValue[] = [{ id: contactId, entityType: “contact”, name: contactName }];
//set a lookup in the form
 formcontext.getAttribute<Xrm.Attributes.LookupAttribute>(‘primarycontactid’).setValue(lookupData);
 
 //set required level
 let getAttribute: Xrm.Attributes.Attribute<any> = formcontext.getAttribute<Xrm.Attributes.StringAttribute>(‘websiteurl’);
 getAttribute.setRequiredLevel(“required”); //or none to make not required
 
 //show or hide a column
 let uiAttribute: Xrm.Controls.StandardControl = formcontext.getControl<Xrm.Controls.NumberControl>(‘industrycode’);
 uiAttribute.setVisible(false); //or true to make it visible

Open a Custom Page

This scenario is becoming more and more common in projects, to achieve this it is recommended to have a button in the ribbon of the main form you want and when you click on that button you can trigger the following code to open the desired custom page, the best thing about this code is that it is generic so it can be used for every Custom Page you have:

export async function OpenCustomPage(primaryControl: Xrm.FormContext, customPageName: string): Promise<Xrm.Navigation.CustomPage>
{
    const recordId: string = primaryControl.data.entity.getId().replace(“{“, “”).replace(“}”, “”);
   
    return new Promise<Xrm.Navigation.CustomPage>(function (resolve, reject)
    {
        const navigationOptions: Xrm.Navigation.NavigationOptions = {
            target: 2,
            position: 1,
            width: { value: 50, unit: “%” },
            height: { value: 50, unit: “%” },
            title: “Custom Page title you want to show to the user”
        };
 
        const customPage: Xrm.Navigation.CustomPage = {
            pageType: “custom”,
            name: customPageName,
            entityName: primaryControl.data.entity.getEntityName(),
            recordId: recordId,
        };
 
        Xrm.Navigation.navigateTo(customPage, navigationOptions).then(
            function (success) {
                primaryControl.data.refresh(false);
                resolve(success);
 
            }).catch(
                function (error) {
                    console.log(‘Error: ‘, error);
                }
            );
    });
}

 

You can create the button using the new command designer or you can use the classic and beloved ribbon workbench like I did for this example:

Call a Custom API

This is my favorite one, Custom APIs are like plugins on steroids, it’s backend code in which you can do whatever you want and the best thing is that you can call this code from other parts of the platform like canvas app, Custom Page, Clow Flow, Custom Connector or from a button.

export async function CallCustomAPI(primaryControl: Xrm.FormContext) : Promise<Xrm.ExecuteResponse>
{
    const recordId : string = primaryControl.data.entity.getId().replace(“{“, “”).replace(“}”, “”);
 
    Xrm.Utility.showProgressIndicator(“processing…”);
    return new Promise<Xrm.ExecuteResponse>(function (resolve, reject) {
        const execute_name_of_your_custom_apip_Request = {
            // Parameters
            Name_of_your_input_parameter: recordId, // Edm.String
 
            getMetadata: function () {
                return {
                    boundParameter: null,
                    parameterTypes: {
                        Name_of_your_input_parameter: { typeName: “Edm.String”, structuralProperty: 1 }
                    },
                    operationType: 0, operationName: “name_of_your_custom_api”
                };
            }
        };
 
        Xrm.WebApi.online.execute(execute_name_of_your_custom_apip_Request).then(
            function success(response) {
                if (response.ok) {
                    response.json().then(function (results) {
                        const OutputParameter1 = results[“OutputParameter1”];
                        const OutputParameter2 = results[“OutputParameter2”];
                        const OutputParameter3 = results[“OutputParameter3”];
                    });
                    resolve(response);
                }
            }
        ).then(function (responseBody) {                
            Xrm.Utility.closeProgressIndicator();
        }).catch(function (error) {
            console.log(‘Error: ‘, error);
            Xrm.Utility.closeProgressIndicator();
            reject(error);
        });
    });
}

You can create the button using the new command designer or you can use the classic and beloved ribbon workbench like I did for this example:

Here’s a tip, you can use the Dataverse Rest Builder plugin from XRMToolbox to create in a few clicks all the code you need to call the Custom API, here you have another blogpost where I explain in detail how to create the Custom Page, how to create the button and how to use Dataverse Rest Builder to create the code that will call the Custom Page:

Call a Clow Flow

This one is very common, an example could be triggering an approval process (the cloud flow) by clicking a button, it is worth mentioning the cloud flow must be an Http trigger: