Dynamics CRM Model-Driven Apps: Developing Frontend Code with Typescript, @types/xrm and webpack

First question: Why TypeScript? We know what is JavaScript programming does. Programming language that sometimes leads us to confusion because its too dynamics. While TypeScript as JavaScript superset trying to fix the whole weakness that it can lead us into. TypeScript offers more strict language (data type) and supports IntelliSense which is easier for a new developer to catch up and accustom to.

In Dynamics CRM itself, we already have @types/xrm. Collection of TypeScript types that we can use so we have a more robust and efficient development environment. So this blog post aimed to set up our project environment until we can deploy it to our CRM environment. We will use webpack to convert our TypeScript code and compile it to JavaScript.

Setup Project

We always begin our project using npm init command. After you set up all this information (name of the project, author, license, etc). Then you need to install these npm packages:

npm i --save-dev typescript @types/xrm webpack webpack-cli ts-loader terser-webpack-plugin

Create tsconfig.json:

{
    "compilerOptions": {
      "outDir": "./dist/",
      "module": "CommonJS",
      "target": "es5",
      "esModuleInterop": true,
      "sourceMap": true
    },
    "include": ["src/**/*"]
  }

Create webpack.config.js:

const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    format: {
                        comments: false,
                    },
                },
                extractComments: false,
            }),
        ],
    },
    entry: {
        new_customdocument: './src/new_customdocument/main.ts',
    },
    module: {
        rules: [{
            test: /\.ts$/,
            include: [path.resolve(__dirname, 'src')],
            use: 'ts-loader',
        }, ],
    },
    resolve: {
        extensions: ['.ts', '.js'],
    },
    devtool: 'inline-source-map',
    output: {
        filename: '[name].js',
        libraryTarget: 'var',
        library: 'fx'
    },
};

If you take a look at the above configuration, you will see the entry object with property new_customdocument. This file we will create later on. We also set devtool: ‘inline-source-map’ to generate TypeScript source map (for debugging purposes).

Update package.json:

{
  "name": "basic-crm-typescript",
  "version": "1.0.0",
  "description": "Sample of how to implement TypeScript for Dynamics CRM",
  "main": "index.js",
  "scripts": {
    "build": "webpack"
  },
  "keywords": [
    "powerapps",
    "dynamics-crm",
    "model-driven-apps",
    "microsoft",
    "typescript"
  ],
  "author": "Temmy",
  "license": "ISC",
  "devDependencies": {
    "@types/xrm": "^9.0.31",
    "terser-webpack-plugin": "^5.0.3",
    "ts-loader": "^8.0.11",
    "typescript": "^4.1.2",
    "webpack": "^5.10.0",
    "webpack-cli": "^4.2.0"
  }
}

Create Our First Typescript Scripting

One of the main benefits of using webpack is to package multiple files into a single file. So we can split our customization based on the entity per function that we will be using (it will make your customization more structural and clean to read). Here is my implementation for this tutorial:

Structure of the project

Create src/new_customdocument/form.ts:

export function formLoaded(context: Xrm.Events.EventContext) {
    initFormCreate(context);
}

export function initFormCreate(context: Xrm.Events.EventContext) {
    const formContext = context.getFormContext();
    if(formContext.ui.getFormType() !== XrmEnum.FormType.Create) return;

    formContext.getAttribute('new_name').setValue('Form TypeScript UI');
    formContext.getAttribute('new_documentdate').setValue(new Date());
}

Create src/new_customdocument/main.ts:

import * as form from './form';

export namespace new_customdocument {
    export const formLoaded = form.formLoaded;
}

This is the demonstration when we enable @types/xrm in our tutorial (we can fully use IntelliSense in our development!):

IntelliSense mode on 🙂

To build the result, we only need to run this command:

npm run build

You can get the result in dist/new_customdocument.js and deploy it to your CRM Environment.

When you want to register the function (in my example, I call this function on formOnLoad): fx.new_customdocument.formLoaded because in webpack.config.json, we set it under fx variable.

The result when we click new record and the form loaded:

You can download the full zip in here. Remember to run npm install command when you want to use it first time.

Related Post

5 thoughts on “Dynamics CRM Model-Driven Apps: Developing Frontend Code with Typescript, @types/xrm and webpack

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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