Last year I’ve started to learn about the PowerPlatform. In the beginning was everything about LowCode/NoCode and Citizen Developer, but I couldn’t understand how this could cover all the requirements that goes beyond that. So in April 2019 I was so happy to hear about the PowerApps Component Framework (PCF), which would allow the ProDevs to do the magic stuff. I’ve started to play with a PCF control and took as example a feature I was missing since ever: an optionset showing the colors that were customized for each option. That time React was not supported, and I’ve implemented everything from scratch. It was working, but was not very reliable. Unfortunately it was almost X-Mas until I could find the time and go on with a better implementation. The new control is now OpenSource and can be found on github: https://github.com/ORBISAG/ORBIS.PCF.ColorfulOptionset.
In this blog I intend to write about where to start writing PCF from the perspective of my experience. I hope I can soon go on with another blogs about the implementation patterns, best practices and troubleshooting. I don’t pretend to know the best practices, I still have some questions, but since I didn’t found much about PCF best practices, and even found anti-pattern in some implementations, I’d like to start talking about how to implement the right way. Maybe this will be the starting point for some discussions and we all can learn from each other .
To be able to build PCF components, you need to be a full stack web developer. You need to know HTML5, ES6+, CSS. You will develop using Typescript and will be using npm ( Package Manager for Node.js: https://www.npmjs.com/get-npm), so you have to get used to them first. Besides that, for more complex components you can use React or Angular. I used React, since I knew already how to handle it.
The PCF specific stuff is build on top of that, and here are the resources I used:
- In the PCF SDK there is a good tutorial about about how to write a PCF component: https://docs.microsoft.com/en-us/powerapps/developer/component-framework/implementing-controls-using-typescript.
- There you also can find a lot of examples: https://docs.microsoft.com/en-us/powerapps/developer/component-framework/use-sample-components
- There is a great community, where a team from Microsoft and community users are doing an amazing work to help you when you get stuck: https://aka.ms/PCFForum. For me, the best community I’ve met.
- There is the https://pcf.gallery/ administred by Guido Preite, with tons of examples having the source code available. If you’re a developer you can find a lot of examples there; if you only need the controls you’ll find the solutions to download.
- There are a lot of other resources listed in the sdk-site: https://docs.microsoft.com/en-us/powerapps/developer/component-framework/community-resources
- I even found a great video on youtube, where Andrew Butenko shows us how to implement a PCF control for an optionset using react and OfficeUIFabric : https://www.youtube.com/watch?v=e7JNgGlI3nE
Thank you all for the great content, for the help and ideas.
Since the tutorial explains step by step how to do it, I won’t get into details. But still … let me explain the big picture.
First we need to use the PowerAppc CLI to set up the Project:
pac pcf init --namespace <YourNamespace> --name <Name> --template field
This will generate the whole content you need for start. You get a project file (.pcfproj). You get the package.json, pcfconfig.json, and the TypeScript config file. With this raw configuration you are ready to go and let the npm packeages get installed. So the next step is
This will take a while and will download all packages and place them in the “node_modules”. You are now ready to open your Visual Studio Code
Project content – The manifest
There are two important files that you will find inside your project folder. The first one is the “ControlManifest.Input.xml”. This file is a description of the parameter for your control. There are 3 main declarations inside: Property, Resource and Feature.
You can specify what parameter your component has, what types they have, and how they are bound to your container. Your parameter can be bound to other attributes on the form. You can define more bound parameters (so you can get and set more attributes with only one PCF component), but for now you need at least one property. Unbound PCFs are not possible right now, but this should come in future versions.
And that’s the declaration in the manifest:
<property name="optionsInput" display-name-key="Property_Display_Key" description-key="Property_Desc_Key" of-type="OptionSet" usage="bound" required="true" />
You can also have parameter that are bound to static values that you define beforehand. This one can be used to define how your control should behave. Static parameter will allow you to configure your component. In the next example, the “Behavior” Parameter allows the customizer to specify if the parameter it’s of type “Attribute” or “Entity”
And that’s how the “Enum” property looks like:
<property name="behavior" display-name-key="Behavior" description-key="Behavior" of-type="Enum" usage="input" required="true"> <value name="Entity" display-name-key="Entity" description-key="Entity names" default="true">Entity</value> <value name="Attribute" display-name-key="Attribute" description-key="Attributes for an entity" >Attribute</value> </property>
🛑 Take care, right now not all attribute types are available for PCF component. For instance you cannot bind lookups, statecode or statuscode. Also the address fields for standard entities are not available.
You always have to declare the resources that are included in your component. You always need to define at least the “code” file.
<resources> <code path="index.ts" order="1"/> </resources>
But usually you also have some css files and maybe some images to declare.
Sometimes you need some more features. When you use them, you need to declare them in your manifest. Examples of features are
- using WebAPI to make requests against CDS
- using Utilities
- some device capabilities like captureAudio, captureVideo, getCurrentPosition, getBarcodeValue, pickFile…
For more information about the manifest, check out the documentation: https://docs.microsoft.com/en-us/powerapps/developer/component-framework/manifest-schema-reference/
Project content- index.ts
The Typescript file has to implement 4 interfaces:
- updateView – here you will need to reflect the changes. When the PCF component changes the value of the parameter, it needs to call the function notifyOutputChange, which is passed as a parameter to the updateView.
- getOutputs :when the platform was notified about the change of the value, it will call the getOutputs, where it expects the new values to be returned
- destroy: here you will need to clean up.
Here you can find more information: https://docs.microsoft.com/en-us/powerapps/developer/component-framework/reference/control
Build and debug
The next step is to build the project. For that use the command
npm run build
Now you are good to go and implement the real content of your component. After the code is implemented, use
npm start watch
This will build your component and start/refresh the debug harness.
Upload the component to your CDS instance
While you are debugging your component, you can upload the PCF component into a CDS Debug-Solution using
pac pcf push -pp <yourPublisher>
This will create the solution PowerAppsTools_<yourPublisher> containing your PCF component, in your CDS instance . This way you can add the component on your form and start testing.
Wrapping it up – packaging the solution
After the component is tested and ready, you need to make another VS project: this time is a Solution project. Following the instructions (https://docs.microsoft.com/en-us/powerapps/developer/component-framework/implementing-controls-using-typescript#packaging-your-code-components) , you will get a solution.zip which you have can distribute.
🛑 In case you need to generate the Solution several times, you need to increment the version your manifest file before starting the generation. Otherwise the component won’t be updated after installation.
My debug experience & broken Harness…
I’ve made a lot of HTMLWebresources for Dynamics 365 before; I used ES6+, I worked with npm and transpiling based on babel (but not with WebPack), I’ve made some React development (but I was not very experienced) and I didn’t use TypeScript before. So I had some challenges beside the PCF itself. But since Andrew Butenko’s Video is showing us how to do an optionset PCF in 7 minutes, how hard could it be? Right?
And actually it was pretty straight forward. Just followed the magic words:
pac pcf init npm install npm run build npm start watch
… and I’m good to go. The harness to develop the component locally opens, I change the manifest to declare that I bind the input to an optionset control and I can start with the actual content. And then, I start to click around in the harness, just to be sure that I have a solid start and BOOOOM… the harness is changing to a complete white page. I could see in the console that there is a parse problem, I’ve closed the harness, even the Visual Studio Code, tried to delete some generated content in my project, trying to see what went wrong: nothing helped. And here I’ve spend a few hours. After a while I’ve changed the name of the parameter, and luckily it started to work again.
So I’ve posted this bug in the community forum, because that helps to have the bug fixed. A few weeks later Andrew Butenko and Ben Thompson answered me that the place where the harness is caching some stuff is the localStorage for the localhost (so http://127.0.0.1:<your port>) and the name of the key is “<controlName>_properties“. So I just need to delete this key and the harness started to work again. Maybe this will be soon fixed.
Even if I had some trouble with the harness which costed me a few hours, at the end of the day I had a working PCF component and was happy with that. But actually the heavy work started only after that: implement the disabled state, trying to have the look and feel of the native controls (and that took me to some more React stuff to learn, like React Hooks and function component). I will come back with another blogs about that.