Build Different with Power Apps portal – Episode 5: Reuse PCF controls on the portal

Power Apps Component Framework (PCF) has been around for a while. The community is super active. Growing numbers of PCF controls can be found at pcf.gallery. Enhancements to user experience (UX) in Dynamics/Power Apps are possible, thanks to PCF.

We have submitted an idea to bring PCF to the portal and it is currently under review.

In this post, I will show you a way to reuse existing PCF controls in Power Apps model-driven apps and canvas apps on the portal.

Please note this is NOT supported by Microsoft. It is solely intended for exploration.

Under the hood of PCF on CRM form

If you have done some sort of development with PCF, you will be familiar with a function parameter notifyOutputChanged in init method and the updateView method.

Every time the value of an attribute bound to a PCF control is changed, the updateView method will get triggered. We write most of our UI rendering there.

Every time we update the value of an attribute bound to a PCF control, we call notifyOutputChanged to let CRM form know the latest value.

This works very well in CRM form as it has a matured Client API and object model. They largely remain unchanged since CRM 2011.

Closing the gap in the portal

However, the equivalent object model is missing in the portal. We primarily use jQuery to manipulate the portal UI and elements. It is frustrating, at least to me, that I have to inspect elements and remember them.

The good news is that two libraries (as my knowledge) exists to fill that gap:

  1. DynamicsPortalScripts by James Novak
  2. XrmPortalJS by Dynamics Code (oh…its’ me)

The library will do nasty jobs getting correct elements.

As a user of the script, I only need to know attributes name to show/hide, to set required fields, to run custom validation logic, and to get/set value to attributes. You can see the usages on my Github.

Bundle.js in Power Apps portal

When we build (npm run build) a PCF component, it will generate bundle.js under out folder.

bundle.js

This is a complete control we can place on any web page, with a few coding. Open it and go to the end. We can see the control’s friendly name. In this case, it’s dynamicscode.ReactControlDemo.

Control name

Now, let’s upload bundle.js as a web file in the portal. Note: allow the upload of .js file, by removing js extension in System Settings.

The uploaded bundle.js would look like this.

Web file

Now, include the uploaded file in the web template. In my example, I use ‘Layout 1 Column’. You can include the script file in any of the web template as long as there is no Liquid tag ‘include’.

Include PCF js file

Next, let’s create a web page with an entity form. (I should have renamed the web page name.)

Entity Form

One more step to include the script from XrmPortalJS (https://github.com/dynamicscode/XrmPortalJS/blob/PCFpoc/Xrm.Portal.js). The better approach is to upload it as a web file. But we are here for exploration, not for the best practice.

XrmPortalJS

Let’s see the result

If everything is fine, you should use the following script in the browser console.

Xrm.Portal.Form.get('AttributeName').useControl('ReactSample')

If it doesn’t work, it will probably because of hard-coded parameter names in my script. Please read along the next sections.

The following is the result on my portal.

Transform a textbox to PCF control

Under the hood of XrmPortalJS

XrmPortalJS handles communication between a PCF control and its object model. When useControl function is called, it will send the value and pass updateValue function as notifyOutputChanged to PCF, and call the updateView of PCF.

When PCF control invokes notifyOutputChanged, updateValue in XrmPortalJS will execute to set the value from PCF to its object model, and again call PCF’s updateView to render the control.

Under the hood of XrmPortalJS for PCF. Note: If you have a different property name in PCF, please update the script.

Limitations

It will be heaps, so these will be major limitations.

First, I am currently hard-coding parameters name (value in the example). It should reflect the property names set in ControlManifest.Input.xml in PCF. I could probably generate those properties as a JSON object using npm scripts.

Second, it can only bind to a single attribute, a single property and it is a text field. I should be able to add multiple bound properties and support more input controls.

Third, I pass bare minimum context parameters to PCF. I need to look through the PCF context model and replicate it. Colin pointed out API requests will not work. While it would be relatively easy to implement retrieve API using Entity List’s OData, CUD (create, update, delete) will be challenging. Anyway, I will worry API requests later as it is not working in canvas apps too.

Last, no DataSet supports yet.

And the list goes on.

Why do I do this?

As I said, this is an experiment. I do not know if PCF is making its way to Power Apps portal.

I tried using Web Component to mimic PCF with a fair amount of success. I even wrote the draft post about it and seems like I will never have to post it.

Since I am against the idea of re-writing the same component, I find a way to re-use PCF on the portal.

As you can see, the PCF team has done a tremendous job. I do not update my existing PCF control to work on the portal. It seems the roadmap of PCF is super solid and future-proof.

However, we need an official object model for Power Apps portal from Microsoft.

Shall we submit an idea to Power Apps team for the client API and object model for the portal?

Please reach out to me if you need help.