The introduction of Power Apps Component Framework (PCF) controls provides developers with a potentially groundbreaking way of extending Dynamics 365’s model-driven app experience, in ways that are currently impossible to do straightforwardly via Web Resources or similar. Developed using Node Package Manager (NPM) and TypeScript, they allow us to replace existing fields and views within the application with bespoke components, that can achieve a wide variety of purposes. For example, you could develop a custom control that loads a customised date picker control, that enforces business logic within the application by ensuring that the date selected exists within the current fiscal year. Microsoft provides a wide variety of samples, and there is a whole gallery dedicated to showcasing examples the community has developed. In short, if you are still working with Web Resources and haven’t even taken a quick look at PCF controls, I would urge you to correct this oversight at the earliest possible opportunity. Just be prepared for an experience vastly different from the norm, using tools that traditional Dynamics 365/.NET Developers may have only heard about before on the grapevine.

I’ve been doing some work with PCF controls recently. Well, I say work in the very broadest sense. I am fortunate to work alongside developers who are able to put amazing things together in lightning speed compared to me, with me then left to tinker around the peripheral output and, more often not, break things even further in the process 🙂 However, as part of this, I’ve gained a good grasp of some of the features and limitations involved when working with the Web API within a PCF control. Currently, developers can access the Dynamics 365’s/the Common Data Services Web API straightforwardly enough to:

  • Create a brand new entity record, by supplying an object containing the required record field values.
  • Delete a record, by supplying the entity name and its globally unique identifier (GUID).
  • Retrieve single or multiple records and, as part of this, defining an OData query to specify the fields to return, sorting rules and any filtering to apply.
  • Update a single record, by supplying the entity name and its globally unique identifier (GUID).

With the functionality listed above, pretty much any type of required business logic can be accommodated and, due to the tools involved, a good underlying knowledge of how to work with OData in the context of Dynamics 365 will be necessary. Particularly if you want to avoid potential errors like the one below when attempting to update a decimal field using the updateRecord Web API function:

An error occurred while validating input parameters: Microsoft.OData.ODataException: Cannot convert a value to target type ‘Edm.Decimal’ because of conflict between input format string/number and parameter ‘IEEE754Compatible’ false/true.

In this example, I was attempting to update an entity record based on a onEvent click call, where the value of a calendar event on the form was being grabbed and passed back to the application to update an entity record. The function to control this was defined as follows:

private onEventClick(args: ClickEventArgs){
    var editableTitle = $(this.calendar.renderEditableEventTitle(args.element, args.resourceId));
	editableTitle.on("change", () => {
	    let newEntity : Entity = {};
		newEntity[this.varEffortCol.name] = editableTitle.val();
		this.context.webAPI.updateRecord(this.targetEntity, args.resourceId, newEntity);
		editableTitle.off("change");
	})
}

The issue came down to the data type specification within TypeScript – namely, it was stored in a variable as a string, surrounded by double quotes, e.g. “90.0”. Although this is a valid number, it is still a string value, and the Web API prevents you from updating the system accordingly. While this is handy from a data management perspective, it does mean that some additional effort is required to ensure that a) the user is only able to enter a valid number in the first place and b) to perform the appropriate data conversion within the code. The first of these requirements can be achieved by simply ensuring that the input element created on the control is configured only to accept numbers:

var editElem = jElement.find("input[type=number]");
if(editElem.length == 0){
    editElem = $(document.createElement("input"));
    editElem.attr("type", "number");
}

Then, it’s just a case of performing the appropriate data conversion at the right instance. So, we can rewrite the above function as follows:

private onEventClick(args: ClickEventArgs){
    var editableTitle = $(this.calendar.renderEditableEventTitle(args.element, args.resourceId));
	editableTitle.on("change", () => {
        let newEntity : Entity = {};
		newEntity[this.varEffortCol.name] = Number(editableTitle.val());
		this.context.webAPI.updateRecord(this.targetEntity, args.resourceId, newEntity);
		editableTitle.off("change");
	})
}

Nice and easy – just the way I like it! 🙂

PCF Controls provide an exciting new way of extending the interface of model-driven apps, often allowing you to make the application look completely unrecognisable from it’s out of the box appearance. And, unlike Web Resources, they are bound directly to existing fields/views within the application, providing a much more tightly integrated experience. However, with some of the controversial changes recently put in place relating to API limits, there is a real question mark as to how far you can utilise them, without you ending up with a huge bill in the process. Certainly, if your PCF control is doing on average 4-5 unique Web API calls every time a record is accessed, and your Dynamics 365 online deployment has hundreds/thousands of seats, this will likely breach any limits in place. Just because you can do something, doesn’t necessarily mean that you should 😉 But, provided you can navigate through these waters successfully, the potential with PCF controls is truly astronomical and is only one that is going be improved further over time.

Share This