Thursday, 6 August 2020

How to use Xrm and formContext in HTML WebResource in Dynamics 365 CRM

Introduction

In this blog we will explore how to pass ‘Xrm’ and ‘formContext’ in HTML pages using the
‘getContentWindow’ client API in Unified Interface of Dynamics 365 CRM so that we can get or set the form attributes inside the HTML web resource.  As we all know, parent.Xrm is going to deprecate in near future so below is the supported way to use the ‘Xrm’ and ‘formContext’ in HTML page.

Suppose there is a HTML web resource on Account entity form which shows notes record related to a Parent Account. And from the HTML page we need to read or set some fields on Account record using formContext and also want to do CRUD operations inside the HTML Page using Xrm.webapi. So, the Xrm and formContext won’t be accessed directly in HTML page. To access, you can follow the below steps:

1. Add the below code in the ‘onLoad’ event handler of Account entity. The below code is written in Typescript so you need to compile it in JavaScript and add it on ‘onLoad’ event of the account form.

onLoad(executionContext: any): void {

let functionName: string = “onLoad”;

try {

//validate execution context

if (!CRMWork_Account_Library.isValid(executionContext)) { return }

//get form context

let formContext = executionContext.getFormContext();

//validate form context

if (!CRMWork_Account_Library.isValid(formContext)) { return }

//Get AccountNotes control

let accountNotesControl = formContext.getControl(“WebResource_AccountNotes”)

//Validate control

if (CRMWork_Account_Library.isValid(accountNotesControl)) {

//get getContentWindow

accountNotesControl.getContentWindow().then(

function (contentWindow) {

//Pass xrm and formcontext

contentWindow.setClientApiContext(Xrm,formContext);

}

)

}

}

catch (ex) {

CRMWork_Account_Library.throwError(functionName, ex);

}

}

In the above code, we are accessing the HTML page using getControl method. Using the getContentWindow() which returns a content window instance representing an IFRAME or web resource we are going to pass the parameter ‘Xrm’ and ‘formContext’ in HTML page.

‘WebResource_AccountNotes’ is the name of the HTML web resource control added on the Account form.

HTML WebResource in Dynamics 365 CRM

2. Bind the above code on ‘Onload’ of the Account form as shown in below screenshot:

HTML WebResource in Dynamics 365 CRM

3. Now, add the following code in your HTML web resource:

<script>

function setClientApiContext(xrm, formContext) {

//To set the attribute on Account form

formContext.getAttribute(“preferredcontactmethodcode”).setValue(1);

//To do CRUD operation

var data =

{

“subject”: “Sample”,

}

// create Note record

xrm.WebApi.createRecord(“annotation”, data).then(

function success(result) {

console.log(“Notes created with ID: ” + result.id);

},

function (error) {

console.log(error.message);

// handle error conditions

}

);

}

</script>

You can see in above function we have set the value of the ‘preferredcontactmethodcode’ attribute on Account record and we created a new note record using Xrm.webapi functions.

Note: The function name defined in the HTML page i.e. ‘setClientApiContext’ should use the same function name while calling in Onload function of Form event handler.

Conclusion

As illustrated above, you can now pass ‘Xrm’ and ‘formContext’ in HTML pages using the
‘getContentWindow’ client API in Unified Interface of Dynamics 365 CRM.

Wednesday, 17 June 2020

Main Form Dialog in Project for the web and D365 PSA




The April 2020 preview release for Model-driven apps has a new feature, which makes it possible to open a record in a dialog. This new feature is called Main form Dialog (MFD). Quoting Microsoft’s blog post about MDF, ” With this feature you can now open a related record entity on a parent or base form without requiring the user to navigate away, your users can stay in context and edit an existing record or create a new one.”
MFD is a developer feature, meaning it takes code to light it up. This blog post is will give you a high-level understanding of how MFD can be lit up so that you have an understanding of how it can help you in your scenarios. Additional code examples and use cases can be found on docs.microsoft.com.

Requirements and goals of the exercise

This blog post will demonstrate how MFD can be lit up for the Project entity in Project for the web (P4W) and D365 PSA. Let’s define the example’s requirements before we light up MFD:
  • When an existing Project record is open and a new record is created from a custom button on the Project form’s ribbon, open the new record in a dialog.
  • When a new Project record is being created and the form has not yet been saved, the custom buttons should not be visible on the ribbon.
Let’s visualize the requirements to make them easy to comprehend:
Image 1. Custom buttons are visible when an existing Project record is open.
Image 2. When a custom button is clicked, a new record opens in a dialog.
Image 3. When a new record is being created and the form has not been saved, the custom buttons on the ribbon are hidden. Note that the custom buttons are also hidden in the new record dialog in Image 2.

JavaScript for MFD dialogs

Let’s look at the JavaScrip that is used to open a new record dialog. In this example, a new dialog opens either in the center or on the right. Feel free to experiment on this feature by changing the values described on docs.microsoft.com.
Create a new web resource per ribbon button and add the related JavaScript. The web resources are needed later on when the ribbon buttons are created. Ribbon Workbench will be used to create the buttons so add your web resources in a solution. If you are customizing P4W, remember the lack of ALM capabilities when it comes to working in the default environment. P4W customizations are, on the date of this blog post, essentially done “straight to production” as there is no named organization support in P4W. Consider using a trial tenant as your P4W development environment to achieve partial ALM for your customizations.
Image 4. Creating a new web resource.
The JavaScrip to open a dialog in the center is as follows:
function d2d_ProjectMfdCenter () {

Xrm.Navigation.navigateTo({pageType:"entityrecord", entityName:"msdyn_project", formType:2}, {target: 2, position: 1, width: {value: 50, unit:"%"}});
}
The JavaScrip to open a dialog on the right is as follows:
function d2d_ProjectMfdRight () {

Xrm.Navigation.navigateTo({pageType:"entityrecord", entityName:"msdyn_project", formType:2}, {target: 2, position: 2, width: {value: 500, unit:"px"}});
}

Create custom ribbon buttons with Ribbon Workbench

Before Ribbon Workbench is fired up, remember to add the entity related to your custom ribbon buttons to your solution. In this example, we’re customizing the Project entity. The Internet is full of guides for Ribbon Workbench so I’m assuming you know at least the very basics of it. Create the buttons you need and place them on the Project form’s ribbon. Where you place your buttons is entirely up to you. Let’s get started with the nitty-gritty for the buttons.

Display Rules

The first thing I’ve done is I’ve created a FormStateRule type of display rule for both buttons. There’s a really good article on display rules by Magnetism so if you want to learn more, check out this blog post. The catch with this rule is that our buttons are disabled when the Project form is in a “create” state. Create essentially means a new, unsaved record.
Image 5. Display rule for buttons.

Enable Rules

The enable rule for both buttons is very straightforward. I’ve set Un-customised (IsCore) to true for both buttons.
Image 6. Enable rule for MFD center.
Image 7. Enable rule for MFD right.

Commands

Here comes the part where we tie the JavaScripts we created to the buttons by creating an action and choosing the related web resource. Remember the function you’ve defined in your JavaScript. Add the display and enable rules that we created in the previous steps.
Image 8. Command for MFD center.
Image 9. Command for MFD right.

Buttons

The last step is to add some details for our buttons. I’ve copied the OOTB “New” button, which is used to create new records. Remember to choose the command created in the previous step.
Image 10. Button for MFD center.
Image 11. Button for MFD right.
With all the steps complete, it’s time to publish and test the buttons. The results should be similar to what is displayed on images 1-3. If you’re comfortable with JavaScript, the next step could be to create something more complicated. For example opening an Account related to a Project.

USING THE NEW MODAL DIALOG TO OPEN FORMS IN DYNAMICS 365 USING XRM.NAVIGATION.NAVIGATETO




We will access these modal forms through JavaScript. In this example, we will select an account record and open the Contact form as a modal.
So we’ll start on an Account record:
The command is:
Xrm.Navigation.navigateTo(pageInput,navigationOptions).then(successCallback,errorCallback);
We will pass through the following command to our browser developer console (you can call this from anywhere you need to):
Xrm.Navigation.navigateTo({pageType:”entityrecord”, entityName:”contact”, formType:2}, {target: 2, position: 1, width: {value: 50, unit:”%”}});
We see the modal Contact form opens over the Account form:
If we click outside the Contact form (on the Account form), we are unable to get focus back to the Account form. The idea here is that the user can be on a Dynamics 365 page, and then view or work on another record, and be able to get back to the original record easily.

Close, Minimize, Maximize

The user needs to click on the X close button or Save and Close.
Also note the option to pop this out to Full Screen Mode:
Which takes up the whole browser window:
We can click to get back to the original modal size:
Let’s look at the options available when opening modals. We are passing objects with the attributes:
Page Input = {pageType:”entityrecord”, entityName:”contact”, formType:2}
Navigation Options = {target: 2, position: 1, width: {value: 50, unit:”%”}}

Size

Let’s open a form to 95%. Note we can pass the width unit as % or px, and then the unit.
We see the 3 columns on the form can be displayed as a result:
Xrm.Navigation.navigateTo({pageType:”entityrecord”, entityName:”contact”, formType:2}, {target: 2, position: 1, width: {value: 95, unit:”%”}});

Position

We can also pass in the Navigation Options position = 2, we the form now opens to the side (1 = center):
Xrm.Navigation.navigateTo({pageType:”entityrecord”, entityName:”contact”, formType:2}, {target: 2, position: 2, width: {value: 500, unit:”px”}});
This is similar to a quick create form, though we’re seeing all the tabs available for selection.
We could enlarge this side view by making the size bigger:
Xrm.Navigation.navigateTo({pageType:”entityrecord”, entityName:”contact”, formType:2}, {target: 2, position: 2, width: {value: 60, unit:”%”}});

Existing Record

To open an existing record, we can do the following, passing the Id of the record to open:
Xrm.Navigation.navigateTo({pageType:”entityrecord”, entityName:”account”, formType:2, entityId:”71f0728d-c25f-ea11-a811-000d3a3be299″}, {target: 2, position: 1, width: {value: 50, unit:”%”}});
Or on the side:
Xrm.Navigation.navigateTo({pageType:”entityrecord”, entityName:”account”, formType:2, entityId:”71f0728d-c25f-ea11-a811-000d3a3be299″}, {target: 2, position: 2, width: {value: 50, unit:”%”}});

Entity List

navigateTo can also be used with with entity lists. For the pageType, passing entiylist will open the list:
Xrm.Navigation.navigateTo({pageType:”entitylist”, entityName:”account”}, {target: 2, position: 1, width: {value: 50, unit:”%”}});
And we can pass the Id of a view to open it:
Xrm.Navigation.navigateTo({pageType:”entitylist”, entityName:”account”, viewId:”61273827-328e-e011-95ae-00155d9cfa02″}, {target: 2, position: 1, width: {value: 50, unit:”%”}});

Web Resources

We can also open web resources. For example, if we have a web resource below:
With the name new_TestWebResource.html:
We can open it like below:
Xrm.Navigation.navigateTo({pageType:”webresource”, webresourceName:”new_TestWebResource.html”}, {target: 2, position: 1, width: {value: 50, unit:”%”}});
And on the side:
Xrm.Navigation.navigateTo({pageType:”webresource”, webresourceName:”new_TestWebResource.html”}, {target: 2, position: 2, width: {value: 50, unit:”%”}});
It looks like Microsoft *could* add more parameters and therefore functionality to this capability, which would be interesting. Andrew Butenko has a good post on some of the limitations with using this for web resources