Step by Step to create GUID PCF Control

Prerequisites:

Components:

There are a few files that make up a PowerApps Component Framework custom control project. The two primary files that make up the control are the manifest file and the typescript file.

The manifest file is an Xml file which contains information about the namespace of the control, the properties of the control and the resources that make up the control which include the name of the typescript file, and any stylesheet or resource files that are included with part of the project.

  • The typescript file…
  • The stylesheet …
  • The resource file…

Manifest File

The manifest file is an Xml file which contains information about the namespace of the control, the properties of the control and the resources that make up the control which include the name of the typescript file, and any stylesheet or resource files that are included with part of the project.

Control Element

The control element contains the namespace and the constructor which were provided when creating the component using the pac pcf init command.

pcf1

The display-name-key is what will appear inside of properties of the control inside Dynamics form editor, when selecting the controls tab, and adding a different control to display on web, mobile or tablet. The description-key is the description that will show up inside of the control properties within Dynamics form editor. The text below shown us the content of the control tag after adding the correct values to the displayname-key and description-key attributes.

<control namespace=”GuidPCFDemo” constructor=”GuidControl” version=”0.0.1″ display-name-key=”GuidControl” description-key=”GuidControl description” control-type=”standard”>

Property Element

By default, when a new PCF custom control project is created, only a single property is available. A PCF control can include multiple properties for different types of controls. The manifest file contains by default the following Xml for the property:

<property name=”sampleProperty” display-name-key=”Property_Display_Key” description-key=”Property_Desc_Key” of-type=”SingleLine.Text” usage=”bound” required=”true” />

The following are the attributes of the property element:

  • Name – this is the name of the property, which will be referred to from the typescript file in order to read and update content from the control.
  • Display Name Key – this is the name of the property that would appear within Dynamics.
  • Description Key – this is the description of the property that would appear within Dynamics
  • Of Type – this attribute represents the data type of the property. When the usage of the of-type attribute is set to bound, then you bind it to the corresponding field within Dynamics. The of-type attribute can contain values such as Currency, DateAndTime, Decimal, Enum and more. The full list is available on the Microsoft Document site.
  • Usage – this attribute can be either bound as previously stated, which means that this property is bound to a control within Dynamics or input which means that it will be used for read-only values.

Resources Element

The final part is the resources. There are no changes required to the resources if your control will only be using the index.ts code file as it is already specified in the manifest file. The code element contains the location of the file where we will develop the custom control and build the HTML elements for it, as well as create the events of what happens to the control when interacted with such as on a click event or a change event. The other two elements which are includes in the manifest file and are part of the parent resources element are css and resx. The css is the stylesheet that will be used for the control. This is not required, but if you want your control to blend into the Unified Interface and look somewhat like other controls on the form, this is highly recommended. You can also use existing styles that are available in Unified Interface and link them to the control itself. You will see this in the next sections. The resx is a file that contains localized content in order to display data for the control in additional languages. For the purpose of this demo, we will not use it. The unchanged resources element looks like this:

  <resources>

<code path=”index.ts” order=”1″/>

<!– UNCOMMENT TO ADD MORE RESOURCES

<css path=”css/GuidControl.css” order=”1″ />

<resx path=”strings/GuidControl.1033.resx” version=”1.0.0″ /> –>

</resources>

Typescript file

index.ts file contain following methods

  • init(Required) – When the Dynamics form is ready, it initializes the PCF component by calling the init method.
  • updateView(Required) – If the data changes, platform calls out the updateView method.
  • getOutputs(Optional)
  • destroy(Required)

 Building Control:

 Create the required files

  • Create 2 folders (i.e., Controls, Solutions) in your drive.
  • Under ‘Controls’ folder, create a sub folder with your PCF control name.
  • Open the ‘Developer Command Prompt for VS 2017/2019’ and point to the ‘Controls -> PCF Control name’ folder. In my case, my PCF control folder name is GuidDemoPCF and folder location is D:\PCF\Controls\GuidDemoPCF.
  • Run pac pcf init command to initialize the project.
pac pcf init –namespace GuidPCFDemo–name GuidControl –template field

pcf2

Install Project Dependencies

After the project has been created, you can navigate to the project directory, and you will notice that a subfolder with the name of the component has been created. The subfolder contains two files (ControlManifest.Input.xml and index.ts).

pcf3

We can now go ahead and install all the required dependencies that are required. This step can take a few minutes to complete. The command to install the dependencies is npm install

pcf4

In your project directory, a node_modules folder was created with a lot of sub folders containing script files. This contains a large variety of available modules that can be added to your typescript project.

pcf5

Update the Manifest File

After the solution has been initialized, the manifest file will look like the below.

<?xml version=”1.0″ encoding=”utf-8″ ?>

<manifest>

<control namespace=”GuidPCFDemo” constructor=”GuidControl” version=”0.0.1″ display-name-key=”GuidControl” description-key=”GuidControl description” control-type=”standard”>

<!– property node identifies a specific, configurable piece of data that the control expects from CDS –>

<property name=”sampleProperty” display-name-key=”Property_Display_Key” description-key=”Property_Desc_Key” of-type=”SingleLine.Text” usage=”bound” required=”true” />

<!–

Property node’s of-type attribute can be of-type-group attribute.

Example:

<type-group name=”numbers”>

<type>Whole.None</type>

<type>Currency</type>

<type>FP</type>

<type>Decimal</type>

</type-group>

<property name=”sampleProperty” display-name-key=”Property_Display_Key” description-key=”Property_Desc_Key” of-type-group=”numbers” usage=”bound” required=”true” />

–>

<resources>

<code path=”index.ts” order=”1″/>

<!– UNCOMMENT TO ADD MORE RESOURCES

<css path=”css/GuidControl.css” order=”1″ />

<resx path=”strings/GuidControl.1033.resx” version=”1.0.0″ />

–>

</resources>

<!– UNCOMMENT TO ENABLE THE SPECIFIED API

<feature-usage>

<uses-feature name=”Device.captureAudio” required=”true” />

<uses-feature name=”Device.captureImage” required=”true” />

<uses-feature name=”Device.captureVideo” required=”true” />

<uses-feature name=”Device.getBarcodeValue” required=”true” />

<uses-feature name=”Device.getCurrentPosition” required=”true” />

<uses-feature name=”Device.pickFile” required=”true” />

<uses-feature name=”Utility” required=”true” />

<uses-feature name=”WebAPI” required=”true” />

</feature-usage>

–>

</control>

</manifest>

We will start by modifying the control element. The information here is based on what was entered in the pac pcf init command, so likely there is not much to modify, but we can change the description or other attributes as required. The result here should look like this:

<control namespace=”GuidPCFDemo” constructor=”GuidControl” version=”0.0.1″ display-name-key=”GuidControl” description-key=”GuidControl description” control-type=”standard”>

Next we will create a bound property for this control which will be based on a single line of text in our model driven application. We will provide the property name, display name key and description, the type of control, the usage (whether it is bound, input or output), and whether it is required. After making the changes it will look like this:

<property name=”GuidField” display-name-key=”GuidPCFDemo_GuidField” description-key=”Record Guid Field” of-type=”SingleLine.Text” usage=”bound” required=”true” />

Finally, we will specify the resources that make up this project. In our case, we will be using a TypeScript file that will include the code elements, and a stylesheet that will define the look and feel of the control.

    <resources>

<code path=”index.ts” order=”1″/>

<css path=”css/guid.css” order=”1″ />

</resources>

After making all the changes to the manifest file, and removing all the comments, the manifest file will be short and clear.

<?xml version=”1.0″ encoding=”utf-8″ ?>

<manifest>
<control namespace=”GuidPCFDemo” constructor=”GuidControl” version=”0.0.1″ display-name-key=”GuidControl” description-key=”GuidControl description” control-type=”standard”>
<property name=”GuidField” display-name-key=”GuidPCFDemo_GuidField” description-key=”Record Guid Field” of-type=”SingleLine.Text” usage=”bound” required=”true” />
<resources>
<code path=”index.ts” order=”1″/>
<css path=”css/guid.css” order=”1″ />
</resources>
</control>
</manifest>

Type Script or Code Component File

We will start by looking at the file looks when it is only created.

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

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

/**

* Empty constructor.

*/

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=’standard’, it will receive an empty div element within which it can render its content.

*/

public init(context: ComponentFramework.Context, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container:HTMLDivElement)

{

// Add control initialization code

}

/**

* 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): void

{

// Add code to update control view

}

/**

* 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 {};

}

/**

* 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

{

// Add code to cleanup control if necessary

}

}

The import and export portions of the file remain untouched, as well as the constructor. We will start by declaring variables above the construction that can be used as shared variables within the class. The list of global variables includes the PowerApps Component Framework required parameters (context, notify changes and the output HTML Div container) and  the HTML elements that will make up the control.

    private _context: ComponentFramework.Context;

private _container: HTMLDivElement;

private _labelElement: HTMLLabelElement;

private  _value: string;

Init Method

The init method contains all the initialization code for the typescript file This includes assigning values to global variables, binding control events to the delegate, skinning the control so that it looks like a control that is similar in look to the Unified Interface and finally creating the div element. To assign the signature values to the public variables we will call the following lines of code. This will be similar in most of your projects. Within the init method we will start by adding the following code:

  this._context = context;

this._container = container;

we will customize the control and add the attributes and an event to the new Label element.

this._labelElement = document.createElement(“label”);

this._labelElement.setAttribute(“id”, “lblguid”);

this._labelElement.setAttribute(“class”, “label-css”);

this._labelElement.innerHTML = “NA”;

We will add label element to to the container that was defined and passed by the control.

  container.appendChild(this._labelElement);

Update View Method

The updateView method is called when any value in the property bag changes, which includes field values, datasets, global values (such as container width and height), control metadata values (such as labels or visibility). The context parameter is the entire property bag that is available to the control via the context object. This parameter contains the values that are set up by the system customizer mapped to names defined in the manifest as well as utility functions

For our Guid field, we will get the record id and set the value

this._context = context;

let entityId = (context).page.entityId;

this._labelElement.innerHTML = entityId;

GetOutputs method

The getOutputs method is called by the framework prior to the control receiving new data. It returns an object for a property that is marked as bound or output. In our case we are not using for it. So, keeping as is.

Destroy method

The destroyer method is used in many programming language to clean up control, remote calls or listeners that might still be consuming resources. In our case we are not using for it. So, keeping as is.

Design the Stylesheet

The following styles are used by the control and set to display the control in a way that is similar to the way controls look in Model-Driven (Unified Interface) applications.

.label-css{

color:green;

font-weight: bolder;

float:left;

}

Build the control

Build the project by triggering npm run build command.

pcf6

Packaging PCF control to a Solution:

let’s package it into a solution which enables us to transport the PCF control to CDS which can be further used in Forms.

  • In the Solution folder which has been created in above steps, create another sub folder for the PCF control. In my case, I named the folder as PCF_ GuidDemo.

D:\PCF\Solutions\PCF_GuidDemo

  • Open the ‘Developer Command Prompt for VS 2017/2019’ and point to the ‘Solutions -> PCF_ GuidDemo
  • Trigger solution init command which creates folder structure.
pac solution init –-publisher-name [THE_NAME_OF_THE_PUBLISHER] –-publisher-prefix [PREFIX_TO_USE_WITH_PUBLISHER]

pac solution init –publisher-name PrasannaV –publisher-prefix prasanna

pcf9

pcf8

  • Trigger solution add-reference command, which links our PCF control with Solution.
pac solution add-reference –path “D:\PCF\Controls\GuidDemoPCF”

pcf9

  • Finally, trigger msbuild command to zip the components. It creates bin/Debug folder along with solution zip file.
msbuild /t:build /restore

pcf10

  • Once we have the solution zip file, we are good to use the PCF control by importing to CDS.

pcf11

Deploy the solution

Now that the solution has been created, we are ready to deploy it in our environment. We will first import the new solution into our environment, create the field inside our Model-driven application, and finally test it out.

pcf12
pcf13

Customize Entity

Open a solution and select the entity where you want to create the field to be used by the control. In our case we will create a field called Guid of data type text.

pcf14

Test the deployed solution

Now that the solution has been deployed, you can test it out. Open the account views where you created the solution and create account record. The control will display the record Guid.

pcf17

References:

  1. https://nishantrana.me/2019/06/06/step-by-step-create-a-very-simple-powerapps-custom-component-to-show-the-guid-of-the-record/
  2. https://bgx.blob.core.windows.net/files/powerplatform/PCFControlGuide.pdf

2 thoughts on “Step by Step to create GUID PCF Control

    1. Hi Saranya , Please do change version number in manifest file and rebuild and same zip file will be update and install back in crm solution and your changes will reflect .
      for deep – refer video its explain all from scrach-

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s