Talking points in Dynamics 365 AI for Sales–Gotchas!

Introduction of Dynamics 365 AI has been a game changer in the field of Dynamics 365 and personally I have seen that mentioning this feature many a times drive the decision makers to choose Microsoft CRM over it’s competitors.

And if you are a Dynamics consultant, it’s obvious that you are have either read it or explored this feature yourself or may be just demoing this to your customer. And here I was demoing some of the features to my customer before being grilled specially with “Talking Point” feature of AI for sales.

This blog is not about configuring and setting it up but rather exploring how it works with various scenarios. Personally I find documentation related to these features in Microsoft docs not to be very detailed and your real life experiences are your best learning. Sharing some of them through this blog.

Although I will explain this feature a bit here but in case you want to learn more about this and how to configure it and get started, click here.

So what is this feature all about? Well, “Talking Points” feature is a great one for sales guys especially in scenarios where you haven’t interacted with your customers for sometime and you want to initiate a conversation. Talking Points is loosely termed as “Ice breakers” or “Conversation starters”. To put in Microsoft words – “In Dynamics 365 for Sales, Talking points provides a mechanism to automatically identify such conversation starters from your emails. The conservation starters include topics that are related to sports, vacation, family, and entertainment. These insights are available on the contact page.”

image

So let’s see the common checklists you can verify in case talking points does not give expected outcome. Please note that some are documented and some are based on my personal observations based on the way functionality works as of time I write this blog. The logic may be changed by Microsoft with time.

1. Verify Connection graph is enabled

While this is one of the step mentioned in Microsoft docs, from personal experience I have seen consultants missing this step. To enable this, login with your office admin account and enable “Connection graph” from Settings –> Services & add-ins –> Dynamics 365 AI for Sales – Connection Graph and enable it.

image

image

2. Email’s sent by you to your customer are not considered.

I believe it’s quite obvious. A sales guy may be sending lots of email to their customers and some of them may fall in the category of talking point. But that does not necessarily mean they can be conversation starters. So only the emails coming from your customer and falls in the category configured for talking points will be considered and shown in CRM UI.

3. It’s the description or email body that matters and not the subject (as per my observation)

Now this can be a confusing one. And honestly it came as surprise for me. So lets take the examples below.

Below one is the email from my customer to me updating me he saw me in football match yesterday.

image

While this email appears when I enable the auto-capture feature in Dynamics, the same does not appear in the talking points section configured although it should have shown up in sports category.

The only talking point that appears now is about family.

image

Now below is the next email in which the customer conveys the same message. But this time in the email body.

image

And now when I open the contact record and check for the talking points section, it lists out as a conversation starter with the customer in “Sports” category.

image

The reason why I put it “as per my observation” is because this is from my experience while setting this up for my customer. Didn’t find anywhere documented though. I would be happy if anyone could find me a link.

4. Talking points displayed are sensitive to the context of logged in user.

Well this one is pretty obvious. But it still gets a mention here because believe it or not, sometimes the simplest of stuffs baffles us.

Dynamics will display only the conversations that took place between CRM user and the contact. For e.g – in the talking points section, the logged in user can only see his/ her past interactions with the contact as conversation starters (provided they match the category). Not related to any role in Dynamics system.

Quite obvious right. No-one should be able to view your conversations with the customer.

5. If I have duplicate contacts with same email address, what would happen?

The answer to this is, it would show up in talking points for both the contacts as the conversation is being tracked based on email address only.

So this was my list. What’s yours? I would be happy to add it here. It’s a new area and loads of stuff to explore.

Hope this helps!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

{In-depth end-end walkthrough} Develop your custom controls using Power Apps Component framework and use it on your CRM interface.

Before I stepped in the wonderful world of Dynamics, I used to develop custom controls in ASP.NET. Couple of days back when Microsoft announced the release of Power Apps component framework using which you can develop custom controls and use it on Dynamics forms, I was overwhelmed. It was kind of nostalgia for me. Going back to the old glory days of custom control development.

And here I was reading the pre-release documentation from Microsoft. https://docs.microsoft.com/en-us/powerapps/developer/component-framework/custom-controls-overview 

As I was reading I could find that while all the pieces are documented, there are certain areas in documentation where developers may get stuck. Also the documentation does not show end to end of how your custom control can end up being used on a CRM Form.

So I am penning down this blog for all my blog readers. A detailed, end-end scenario where you will develop your custom controls and use in CRM eventually.

To keep each blog short -  I have divided it into a series of blogs.

Part – I  – Understanding Custom Component Framework and control lifecycle

Part – 2 – Setting up development environment and Custom Component Project

Part – 3 – Set-up Manifest file for your custom control

Part – 4 – Develop your Power Apps Custom Control UI and events

Part – 5 – Build, Test and Deploy your Power Apps Custom Control

Part – 6 – Embed your Custom control on CRM form

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

Part 6 – Embed your Power Apps Custom control on CRM form

The article is a part of series of blog posts on Custom component framework topic. In order to get the context I would suggest to get started from beginning.

In our previous article, we learnt how to build and deploy our custom control to CRM environment. To test it, I will use the account entity.

I will create three fields first in account entity

1. File Control – Single Line of Text

2. File Size: Whole Number

3. File Name: Single Line of Text.

4. Content – Single Line of Text (Format – TextArea)

I will place them on the form. This is what my form look like post above steps.

image

I will put my control for File Control field. So I double click to edit it. And what a treat! I could see my FileControl right up there. If you remember, while defining the manifest file, I created the type-group for whole number and Single Line of text field. Since FileControl is single line of text, hence my control is showing up.

image

Again in the manifest, we have put it to bound. So you need to select the bound attribute for each property we defined in manifest file.

image

Awesome. Isn’t it? Now just save and publish.

Now finally when I see the unified interface, I could see the below

image

And when I select a file, I can see FileName and FileSize fields getting updated.

Even if you want upload a file more than 1 MB and click on Submit button, the validation fires. A treat to eyes when you see something working.

image

Hope this helps!

Debajit Dutta

(Business solutions MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com or our training page http://www.xrmforyou.com/training-.html

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

Part 5 – Build, Test and Deploy your Power Apps Custom Control

The article is a part of series of blog posts on Custom component framework topic. In order to get the context I would suggest to get started from beginning.

Now that we have developed our control in the previous article it’s time to build, test and deploy.

The first is to build your component. To build you need to open Visual Studio 2017 developer command prompt and navigate to folder where your code file is there (index.ts).

In my case it is c:\Debajit\Blog\PowerControls\FileControl

image

Once in the directory, run the command “npm run build”

image

As you can see, Build is successful. Now it’s time to test whether your control is rendering correctly before we deploy it to CRM.

Just type “npm start” in command line. It will launch IE process and show you. As you can see from screenshots my file control with submit button is rendered successfully. Look’s ugly but works just fine.

image

image

So build successful and tested as well. Now we need to put in CRM. But how?

The first thing we need is to create a solution file (zip archive) and bundle our custom component inside that solution. Before I do that, I create a new folder called “Deployment” inside my “PowerControls” folder and navigate to that folder from Visual studio command prompt. In my case the full path is “C:\debajit\blog\powercontrols\deplpoyment”.

I then run the below command

pac solution init --publisherName <enter your publisher name> --customizationPrefix <enter your publisher name>

Here in publisher name I put – “xrmforyoucontrols” and in customizationPrefix I put – x4uctrl. So my command line is

pac solution init --publisherName xrmforyoucontrols --customizationPrefix x4uctrl. Basically it creates a publisher with the specified customization prefix.

You will get notified in the console that deployment is successful.

image

The next step is to add our custom control reference. To do this run the below command.

pac solution add-reference --path <path or relative path of your PowerApps component framework project on disk>

Please note here that the path is till the directory where your component directory resides. My component directory is “FileControl” and is within C:\Debajit\Blog\PowerControls

image

To generate the solution zip file, the final step is to run first – “msbuild /t:restore” and then once that is completed, run “msbuild”

MSBUILD /t:restore

image

MSBUILD

image

And finally when I open my deployment folder, I could see bin folder. Navigate inside bin\debug and you would find your solution file.

image

Import the solution file into your environment and publish all customizations.

The final step is using the control in CRM which is covered in the next article.

Part 4 – Develop your Power Apps Custom Control UI and events

The article is a part of series of blog posts on Custom component framework topic. In order to get the context I would suggest to get started from beginning.

So now we are where it matters the most. In this article we will write code to develop our custom control, register events to our controls so that our control behaves dynamically with response to use interactions.

If we remember from start, we would be developing a HTML file input control and a submit button. So let’s open our code file – index.ts. I use Visual studio 2017 to open my file.

You will see a bare bone class with some methods in place that we described in one of our previous article.

image

All we need is to implement these methods. A prior knowledge of type script definitely help. But believe me a little bit of practice and you should be up and running.

First we are going to define some variables for our control. Let’s start with defining variables for our control image

I defined three HTML elements in typescript. To represent the file control and submit button. The breakelement is to represent the “<br />” tag.

Next I define the properties that I would play with. If you remember while creating the manifest, we defined three properties – FileName, FileSize and Content. I will define variables in my code for all three properties of the control.

image

Next I declare variables for event handlers. I will register two event handlers. The first one to handle onchange of input file control and the second one to handle the click event of the button.

image

The final set of variables. I will define

  • a local variable for to hold the control context which has all information regarding the control
  • one delegate to handle the notifyOutputChanged event which is fired when the control has new outputs to be received 
  • A HTML div container which will contain the final set of UI elements to be bound to the UI.

image

OK..our variable declaration is done. Now the main method to focus is the init method. Below is the complete code of my control. If you observe inside the init method I am creating my control and registering the onchange and click event handlers.

Inside the change event handler of the file, I am getting the file information and calling the _notifyOutputChanged() method which in turn calls the getOutput method.

Also in the updateView method, observe how I am accessing the CRM controls bound to individual properties. And setting them with the values from properties of the control we defined earlier. The context object contains entire control information including the client details and page details as well.

Some places you would find @ts-ignore command. This is because I have used Xrm.Page which typescript is not aware of. Hence I explicitly put a statement so that the compiler ignore that line during build to prevent build errors.

Now that we are done with the control, the next step is to build and deploy. Please refer to the next article

Context screenshot:

image

Control code:

import {IInputs, IOutputs} from "./generated/ManifestTypes";

export class FileControl implements ComponentFramework.StandardControl<IInputs, IOutputs> {

    /** variable for HTML elements */
    private _fileElement: HTMLInputElement;
    private _submitButton: HTMLElement;
    private _breakElement: HTMLElement;

    /** variable for file properties */
    private _fileName: string;
    private _fileSize: number;
    private _content: string;

    /** event variables */
    private _submitClicked: EventListenerOrEventListenerObject;
    private _fileChanged: EventListenerOrEventListenerObject;

    private _context: ComponentFramework.Context<IInputs>;
    private _notifyOutputChanged: () => void;
    private _container: HTMLDivElement;

    constructor()
    {

    }

    /**
     * Used to initialize the control instance. Controls can kick off remote server calls and other initialization actions here.
     * Data-set values are not initialized here, use updateView.
     * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
     * @param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
     * @param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling ‘setControlState’ in the Mode interface.
     * @param container If a control is marked control-type=’starndard’, it will receive an empty div element within which it can render its content.
      */
    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container:HTMLDivElement)
    {
        // assigning environment variables.
        this._context = context;
        this._notifyOutputChanged = notifyOutputChanged;
        this._container = container;

        // register eventhandler functions
        this._submitClicked = this.submitClick.bind(this);
         this._fileChanged = this.fileChanged.bind(this);

        // file control
        this._fileElement = document.createElement("input");
        this._fileElement.setAttribute("type", "file");
        this._fileElement.addEventListener("change", this._fileChanged);

       
        // break (<br/>) element
        this._breakElement = document.createElement("br");

        // submit button
        this._submitButton = document.createElement("input");
        this._submitButton.setAttribute("type", "button");
        this._submitButton.setAttribute("value", "Submit");
         this._submitButton.addEventListener("click", this._submitClicked);

        // finally add to the container so that it renders on the UI.
        this._container.appendChild(this._fileElement);
        this._container.appendChild(this._breakElement);
        this._container.appendChild(this._submitButton);
    }

    /**
     * Called when any value in the property bag has changed. This includes field values, data-sets, global values such as container height and width, offline status, control metadata values such as label, visible, etc.
     * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
     */
    public updateView(context: ComponentFramework.Context<IInputs>): void
    {
        debugger;

        // CRM attributes bound to the control properties.
        // @ts-ignore
        var crmFileNameAttr = this._context.parameters.FileName.attributes.LogicalName;

        // @ts-ignore
        var crmFileSizeAttr = this._context.parameters.FileSize.attributes.LogicalName;
        // setting CRM field values here.
        // @ts-ignore
        Xrm.Page.getAttribute(crmFileNameAttr).setValue(this._context.parameters.FileName.formatted);

        // @ts-ignore
        Xrm.Page.getAttribute(crmFileSizeAttr).setValue(this._context.parameters.FileSize.formatted);
     }

    /**
     * It is called by the framework prior to a control receiving new data.
     * @returns an object based on nomenclature defined in manifest, expecting object[s] for property marked as “bound” or “output”
     */
    public getOutputs(): IOutputs
    {
        return {
            FileName: this._fileName,
            FileSize: this._fileSize
        };
    }

    /**
     * Called when the control is to be removed from the DOM tree. Controls should use this call for cleanup.
     * i.e. cancelling any pending remote calls, removing listeners, etc.
      */
    public destroy(): void
    {
        // remove the event handlers.
        this._fileElement.removeEventListener("change", this._fileChanged);
        this._submitButton.removeEventListener("click", this._submitClicked);
    }

    // event handlers
    public fileChanged(evt: Event): void {
        debugger;
         var files = this._fileElement.files;

        if (files != null && files.length > 0) {
            var file = files[0];

            var fileName = file.name;
            var fileSize = file.size;
           
            this._fileName = fileName;
             this._fileSize = fileSize;

            // this will call the getOutputs method.
            this._notifyOutputChanged();
        }
    }

    public submitClick(evt: Event): void {
         debugger;
        // do your file processing here
        var files = this._fileElement.files;

        if(files != null && files.length > 0) {
            var file = files[0];

            var fileSize = file.size;

            if (fileSize > 1048576) {
                // you can alert here…for brevity showing Xrm.Utility..you should use Xrm.Navigation
                // @ts-ignore
                Xrm.Utility.alertDialog("File size should be less than 1 MB");

                this._fileName = "";
                 this._fileSize = 0;

                this._notifyOutputChanged();
            }
        }
    }
}

Part 3- Set-up Manifest file for your custom control

The article is a part of series of blog posts on Custom component framework topic. In order to get the context I would suggest to get started from beginning.

As I explained in the previous article we are going to develop a file control with a submit button. So we need to prepare the Manifest file. As I explained earlier, manifest file defines the field properties and including the data types for which the control is supported.

Navigate to the folder where you have set up your component project. In my case it is – “C:\Debajit\Blog\PowerControls”.

image

As you can see, a folder has been created with the same name we provided in the earlier article for component name – “FileControl”. Navigate inside the folder. You will find two file which are of importance to us.

1. ControlManifest.Input.xml

2. index.ts

Open ControlManifest.Input.xml in suitable xml editor of your choice. I open it with Visual studio 2017.

You will find the namespace and constructor having the same values we provided while creating the component framework project.

image

Let’s start to deep dive here. The first thing you need to understand is the control tag. Namespace and constructor I have just explained. The other two control attributes are

  • display-name-key – The display as would appear for the control in CRM UI. I put it as – XrmForYouControls.FileControl
  • description-key – The description for control as would show up in CRM UI. Input it as – File control from Xrmforyou

This is what my control tag looks like after I put in the above values.

<control namespace="XrmforyouControls" constructor="FileControl" version="0.0.1" display-name-key="XrmForYouControls.FileControl" description-key="File control from Xrmforyou" control-type="standard">

The next thing you need to set-up are the properties of the control. Since we are building a HTML file control with submit button here, we will create three properties

  • FileName
  • FileSize
  • Content

<control namespace="XrmforyouControls" constructor="FileControl" version="0.0.1" display-name-key="FileControl_Display_Key" description-key="FileControl_Desc_Key" control-type="standard">
   <!– property node identifies a specific, configurable piece of data that the control expects from CDS –>
   <property name="FileName" display-name-key="FileControl_FileName" description-key="The name of the file uploaded" of-type="SingleLine.Text" usage="bound" required="true" />
  <property name="FileSize" display-name-key="FileControl_FileSize" description-key="The size of the file in bytes" of-type="Whole.None" usage="bound" required="true" />
  <property name="Content" display-name-key="FileControl_Content" description-key="The base64 content of the file" of-type="SingleLine.TextArea" usage="bound" required="true" />

Let’s analyze the attributes of property here

  • name – the name of the property
  • display-name-key – the name of the property as it would appear in the CRM UI when you configure this control.
  • description-key – Description for the property that would appear in CRM UI
  • usage – can have three values. bound, input or output. The usage attribute identifies if the property is meant to represent an entity attribute that the component can change (bound) or read-only values (input)
  • of-type – This one is important and denotes the data-types for each property. If the usage is specified as bound, then for each of the properties you can only bind it to the corresponding field type as specified here. For details of types supported by Power Apps component framework, refer here – https://docs.microsoft.com/en-us/powerapps/developer/component-framework/manifest-schema-reference/type

Next is “type-group”. So what it type-group. Suppose you want to insert this control only for Single Line of Text fields and Whole Number fields of format – “none”. Using type-group, I can specify these two data types so that in CRM UI, while configuring this control, it would only show up for Single Line of text field and Whole Number field of format – “none”.

Assume I want this control to be available for these two type of fields only. This is what I put as my “type-group”.

<type-group name="filetypes">
        <type>Whole.None</type>
        <type>SingleLine.Text</type>
  </type-group>

I name the type-group as “filetypes” (can be anything). And then I put in the appropriate types for which the control is supported.

We are almost towards the end of Manifest file. The next tag in resources. By default you would see the below XML.

<resources>
      <code path="index.ts" order="1"/>
      <!– UNCOMMENT TO ADD MORE RESOURCES
      < css path="css/FileControl.css" order="1" />
      < resx path="strings/FileControl.1033.resx" version="1.0.0" />
      –>
< /resources>

The resources tag has primarily three child tags

  • code – This contains the path of the file where we would write code to develop our custom control. This is where we would construct the HTML UI for our control, register dynamic behaviors for our control like – “onchange”, “onclick” etc. As you can observe, index.ts (typescript) file is already specified. It’s created by default whenever you create custom component project.

image

  • css – Very simple I guess. The css file to style your control
  • resx – The resource file to contain localized strings you define. As you can see, suggested file name for english (1033) is provided

I will keep this simple. I will just deal with the code part here. Styling has got no surprises. All you need to make sure that these paths are all relative to where your manifest file is located.

So that completes our manifest file. Full manifest file content pasted below. Refer to the next article to see how you can develop your custom control UI with events

<?xml version="1.0" encoding="utf-8" ?>
< manifest>
  <control namespace="XrmforyouControls" constructor="FileControl" version="0.0.1" display-name-key="XrmForYouControls.FileControl" description-key="File control from Xrmforyou" control-type="standard">
    <!– property node identifies a specific, configurable piece of data that the control expects from CDS –>
    <property name="FileName" display-name-key="FileControl_FileName" description-key="The name of the file uploaded" of-type="SingleLine.Text" usage="bound" required="true" />
   <property name="FileSize" display-name-key="FileControl_FileSize" description-key="The size of the file in bytes" of-type="Whole.None" usage="bound" required="true" />
   <property name="Content" display-name-key="FileControl_Content" description-key="The base64 content of the file" of-type="SingleLine.TextArea" usage="bound" required="true" />
    <type-group name="filetypes">
         <type>Whole.None</type>
         <type>SingleLine.Text</type>
   </type-group>
    <resources>
      <code path="index.ts" order="1"/>
     </resources>
  </control>
< /manifest>

Part 2: Setting up development environment and Custom Component Project

The article is a part of series of blog posts on Custom component framework topic. In order to get the context I would suggest to get started from beginning.

For this article I will use Visual studio 2017 for development purpose. All the steps mentioned below will assume that you have Visual studio 2017 as your development environment. Also please note that of the current pre-release, you can set-up your development environment for machines on Windows 10

For this article

Machine OS: Windows 10

IDE: Visual studio 2017

Local directory for control development: c:\debajit\blog\powercontrols

Please follow the below steps:

Step 1: Install NPM

npm is the world’s largest software registry and open source developers use npm to share software. node.js come with npm.

Navigate to site – https://nodejs.org/en/

image

Dowload the LTS one. You can even use the current version (12). Once downloaded install it.

Step 2: Install Power Apps CLI (command line interface)

You can download the CLI from – http://download.microsoft.com/download/D/B/E/DBE69906-B4DA-471C-8960-092AB955C681/powerapps-cli-0.1.51.msi. This will download a MSI file. Install it.

Step 3: Set-up your Power Apps custom component project

1. Open Visual studio 2017 command prompt

image

2. Navigate to your local directory where you want to set-up your component project

image

3. To create a new component project, run the below command

pac pcf init --namespace <specify your namespace here> --name <put component name here> --template <component type>

An explanation is in order here.

“namespace” is the namespace that you want to provide for your controls. For example if you are an ISV and want to develop custom components, may be you want all your controls within a namespace that identifies your company. In my case I would use – “XrmforyouControls”.

“componentname” is the name of the control. Since I will be building a file input control here, I will use the component name as “FileControl”.

“template” – As of the current pre-release only two values are supported for this field and dataset

So my command line would be

pac pcf init --namespace XrmforyouControls --name FileControl --template field

image

As you can see, my project is created successfully.

4. The next step is to install project dependencies. Your component project would required lots of external files to build successfully. To install the dependencies, run the command “npm install”

image

It may take some time to install the dependencies. Your screen would resemble above while installing. Once installation is done, your project environment is ready and we will start building the control.

The first step as we discussed earlier in to build the manifest file which is explained in the next article.

 

Part 1: Understanding Custom Component Framework and control lifecycle

The article is a part of series of blog posts on Custom component framework topic. In order to get the context I would suggest to get started from beginning.

Let’s not get to the gory details and lets try to understand the custom component framework in very simple term. When you design a custom component, let’s understand the basic things you need to develop the control.

  • The first thing is you need to define the behavior of the control. What data type it supports? What are the custom properties that you want to define for the control? This is defined by a XML file called Manifest.xml.
  • What ever custom component you develop, that would eventually render in the browser as HTML. Whatever you want to render is your choice but when your control loads and renders on CRM Form, it will be HTML elements. And like any other control, the custom component that you are going to develop goes through its lifecycle, starting from initialization to rendering on the form. So you need to implement the following methods
    • init – for initialization of the control. Here you build your control with the HTML elements that would be finally rendered on CRM form.
    • updateView – Method is fired when any property of your control changes. This include field value or metadata related to field like height, width, visibility
    • getOutputs – It is called by framework when the data related to control changes. Here you can get the latest value of the control
    • destroy – This function is called by framework when component is removed from DOM tree. Here you can perform any clean-up required.

First thing is then we need to define the Manifest then. In this blog we will just focus on the Manifest file. In the next blog (mentioned below), we would define the application life cycle events.

But wait? We haven’t decided what control we are going to build. In the documentation by Microsoft, you will see sample references to various type of custom controls. But believe me we are not restricted by that. At the end it’s just native HTML, that you would render right? The entire power is in your hands after all.

For this series, we would build a File upload control with a Submit button. When the submit button is clicked, the system would populate the file properties (e.g – filename, filesize etc) in various CRM fields on the form.

The first step in building you control is to set-up your development environment. The next article shows you how to set-up your development environment and create a Power Apps custom component project.

Custom Controls in Dynamics 365 Business Process flows

Today I was just searching some stuffs on Custom Controls and then stumbled upon this link – https://docs.microsoft.com/en-us/business-applications-release-notes/October18/microsoft-flow/custom-controls-in-business-process-flows

Although the documentation tell that it is possible to embed custom controls in Business Process flow, it does not tell explicitly on how it can be done.

And finally after much searching I found it in Microsoft Flow Community blog – https://powerusers.microsoft.com/t5/Microsoft-Flow-Community-Blog

I could find some really wonderful posts there and I would sincerely suggest you to read this.

Now coming back to this article. I have been asked about how to put custom controls in Business Process flows for sometime by Customers but all this time I said “No it can’t be done”. But now we can do that. So without wasting more time let’s do it.

Let’s take the simplest business process flow here which comes OOB  – “Lead to Opportunity Sales process”.

image

As you can  see from the above screenshot, there is field called – “Estimated Budget” which is of type currency in the first stage of the business process flow which is Qualify. Normally this would render as a textbox in your business process flow. How about rendering it as more visually appealing control.

But wait you need to do bit of XML manipulation here. So let’s follow the steps.

  • Create a Solution
  • In the solution add the Lead Entity using “Add Existing” feature and add only the Lead form for the entity.
  • We all know that corresponding to each Business Process flow, an entity is created in CRM. Add the entity corresponding to our Lead to Opportunity sales process flow. The entity name will be same as the Business Process flow name.

You should should look like this.

image

Now I open the lead form in form editor. If you observe carefully, I have couple of field in the Qualify stage of business process flow that I will play with. One is the “Estimated Budget” which I mentioned earlier and the other is “Purchase Timeframe”

I put both the fields on the form.

image

I go to the field properties and change the control for Budget amount to Radial Knob and for Purchase timeframe to Optionset.

image

image

I save and publish the form. Now when I open the lead form, I could see the new controls on the form but the business process flow still shows the old controls.

image   image

So changing at the form level is not making the change at Business process level.

So let’s accomplish this. Export your solution as Unmanaged and once the solution is successfully exported, unzip your unamanged solution.

image

Three files as you can see. No surprise in this.

Open customizations.xml in an editor of your choice. What we will do hear is make the changes for budgetamount field in BPF but keep purchase timeframe untouched.

In the lead form xml of the lead entity search for “budgetamount” field.

image

The important thing here is the uniqueid highlighted in yellow. Make a note of that.

Now with the same uniqueid, search in your customization.xml file. You will find the custom control description for this budget amount field. Copy the controlDescription for this field. In my case it is as below

<controlDescription forControl="{0487895c-be18-985a-c3d4-1540e3d2ed86}">
                   <customControl id="{533B9E00-756B-4312-95A0-DC888637AC78}">
                    <parameters>
                      <datafieldname>budgetamount</datafieldname>
                    </parameters>
                  </customControl>
                   <customControl formFactor="0" name="MscrmControls.Knob.RadialKnobControl">
                    <parameters>
                       <value>budgetamount</value>
                      <min static="true" type="Whole.None">1</min>
                      <max static="true" type="Whole.None">100000</max>
                       <step static="true" type="Whole.None">200</step>
                     </parameters>
                  </customControl>
                   <customControl formFactor="1" name="MscrmControls.Knob.RadialKnobControl">
                    <parameters>
                       <value>budgetamount</value>
                      <min static="true" type="Whole.None">1</min>
                      <max static="true" type="Whole.None">100000</max>
                       <step static="true" type="Whole.None">200</step>
                     </parameters>
                  </customControl>
                   <customControl formFactor="2" name="MscrmControls.Knob.RadialKnobControl">
                    <parameters>
                       <value>budgetamount</value>
                       <min static="true" type="Whole.None">1</min>
                       <max static="true" type="Whole.None">100000</max>
                       <step static="true" type="Whole.None">200</step>
                    </parameters>
                  </customControl>
       < /controlDescription>

So we have copied the uniqueid value and the Control description.

Now within the entity of our Business process flow, you would find 4 tabs.

image

These tabs are nothing but stages of the business process flow. If you remember, the Lead to Opportunity sales process flow has four stage and hence four tabs. Also if we remember, our budget amount field was in the first stage – Qualify.

So expand the first tab and locate for the budgetamount field.

image

Put the uniqueid attribute as we copied earlier.

image

Now after the tabs section, place the customControlDescription that you copied earlier for budgetamount field. Please note it should be inside <controlDescriptions> tag.

image

All done. Save your customization.xml and re-zip your files. Import the new zipped file back to your environment. And now you can see the wonderful custom control in your Business Process flow as well.

image

You must be seeing Purchase timeframe is still rendering as regular optionset. The reason is we didn’t do anything for that field. We just modified the Budget amount field. Take it as lab exercise and do it yourself.

Wonderful isn’t it?

Hope this helps!

Debajit Dutta

(Business solutions MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com or our training page http://www.xrmforyou.com/training-.html

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

What is “Toast Notification Display time” in Dynamics 365

Well this blog is pure serendipity. I was doing something else when I discovered this sitting quietly in Dynamics (not sure when it came in) and then I explored it. What I am talking about here.

If you open a Unified APP, when you click on the small gear icon on the top right of your command bar, you would see an option – “Toast Notification Display Time”.

image

What is this exactly? If you read the whole word together, it may sound gibberish but it’s actually quite familiar if you in web designing and you know the term – “Toast Notification”.

So let’s break it – It is “Toast Notification” + “Display time”. So what is toast notification.

In UI (or I would say UX) world, toast notification is a small message that shows up in a box at the bottom of the screen (position may vary) and disappears on its own after few seconds. It is a simple feedback about an operation in which current activity remains visible and interactive.

If you carefully read the definition above and specially the one I have highlighted in bold, it is a notification or action message which is visible on the screen for few seconds only. But how much are these “few seconds”?

And that is where this setting comes into the picture.

If you click on that option, you would get the below screen.

image

Once you click “OK” on the above screen, you actually increase the notification timeout to 10 times its default.

So now I hope you understand what is this setting all about. But where in CRM where I can test this. Sometime the most obvious things that we see every day are difficult to re-collect when required.

We all have used the Quick create feature. When we create a record using Quick create, we get a notification “Your changes were saved” and also gives us an option to view the record.

image

Normally this notification would remain on the screen for around 8~10 seconds. However when this setting is enabled, this notification would last on the screen 10 times of the default time.

We understood the what and how part. But how can I leave my blog readers leave without understanding the “WHY” part.

This feature has been introduced by Microsoft to facilitate users with cognitive disabilities or users who take more time to comprehend and react to UI elements than average users.

P.S – This feature is only available in Unified interface. Enabling this has no effect on the Classic Web UI.

Hope this helps!

Debajit Dutta

(Business solutions MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com or our training page http://www.xrmforyou.com/training-.html

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)