Create a new PCF Button Control

  1. Create a new folder in your directory

2. Open Visual Studio Developer 2019 command prompt and navigate to the NewPcfButton folder, and type the following pcf command:
pac pcf init –namespace CanvasAppClosePcfControl –name CanvasAppClose –template field

You should see a pcf project getting created in the NewPcfButton folder.

3. Open Visual studio code, and open this project by navigating to the NewPcfButton folder

4. Now, we will need to install the project dependencies. Click on Terminal in the visual studio code ribbon and select New Terminal. Type the command in the terminal – npm install

You’ll notice a new folder “node_modules” created in the NewPcfButton folder
5. Next, type npm run build to build the solution

6. Type npm start to watch the pcf control in your local browser. You can debug and test your pcf control here

Now that we have the pcf project created, built, and run successfully, let’s go ahead and customize and add a new PCF button control. In this post, we will have not have either a bound/unbound control. Therefore, in your ControlManifest.Input.xml file, command out the following line:

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

Next, In your index.ts file, define the following global variables and an eventSubmitClicked event

private _context:ComponentFramework.Context<IInputs>;
private theNotifyOutputChanged:() => void;
private _container:HTMLDivElement;
//Html Elements - Creating a text box and a button

private _eleMainContainer:HTMLDivElement;
private _eleButton:HTMLButtonElement;
private eventSubmitClicked:EventListenerOrEventListenerObject;

Next, inside the init function, write the following code:

this._container = container;
this._context = context;
this.theNotifyOutputChanged = notifyOutputChanged;
//The assignment of the event listener to the function should be done before creating the UI        

this.eventSubmitClicked = this.submitClicked.bind(this);
//Create UI        

//Main Container
this._eleMainContainer = document.createElement("div");
this._eleMainContainer.className = "mydiv";
//Define a button
this._eleButton = document.createElement("button");
this._eleButton.className = "canvasAppButton";             
this._eleButton.innerHTML = "Finish";
this._eleButton.addEventListener("click", this.eventSubmitClicked);
//Add the button inside the main container, and the main container inside the container


Let’s give this button some css styling. Notice, I have a css class “canvasAppButton” attached to this button. The idea here is to apply css to the button control, the same css styling as that of the Canvas App buttons. Create a new subfolder “css” under the main project folder and add the canvas.css file.

Inside the css file, apply the css properties to the class

    border-radius: 8px;
    font-family: “Open Sans”, sans-serif;
    font-weight: 600;
    font-size: 16pt;

Reference this css file under the ControlManifest.Input.xml file in the <resources> section.

Now, that the button is created, we bind the button to the submitClicked event. Write the following function below your init function.

//Custom event handler – for the button
 private submitClicked(event: Event): void{  alert(“Button is clicked”);    }

Next, build the project using npm run build, and npm start to see the button in action

Click on the button.

The pcf button control works!!


Let’s work on deploying this pcf control to CRM

The first step is to create a solution folder inside the NewPcfControl project folder

The next step is to create a publisher and publisher prefix. This will bind the control to the given publisher and the publisher prefix. When this is imported into CRM, a new publisher and the publisher prefix is created with the given names and the pcf control is bound to that prefix. You could also make use of your existing publisher and publisher prefix if you don’t want to create a new one. Type the following command in the Developer Command prompt for VS 2019

pac solution init –publisher-name MyCompany –publisher-prefix new

The next step is add the pcf control project solution reference to the solution folder. Type the following command, but make sure you replace the path with your project path

pac solution add-reference –path “C:\Users\HameedHussain\Downloads\NewPcfButton”

Next, build the solution directory, type the following command:

msbuild /t:build /restore

This command will build the CRM zip file, that you will use to import your solution into CRM. Let’s look at the Solution and see where we would find the solution zip file

The CRM zip file is found inside the bin folder

Import the file into CRM, and use the PCF control as you see fit in any entity.

Additional Notes:

By default, the solution imported will have the display name and Name of the solution as “Solution”. The default solution version is 1.0 This is because the solution.xml contains the unique name, and description of the CRM solution as “Solution”. You can change the Unique name and Name of the solution as per your solution naming convention. See below.

If you make changes to the Pcf control code and wish to import the new changes, just run the build command (npm run build) and make directory (msbuild /t:build /restore), and import the solution. It’s a good practice to update the solution version on every build.

‘The ‘version’ attribute is invalid – The value ‘1.0’ is invalid according to its datatype ‘versionType’ – The Pattern constraint failed.’

While implementing the PCF control, after building the solution, if you run into the following issue while importing the custom control solution

String”>An error has occurred. Try this action again. If the problem continues, check the Microsoft Dynamics 365 Community for solutions or contact your organization’s Microsoft Dynamics 365 Administrator. Finally, you can contact Microsoft Support. : Microsoft.Crm.Tools.ImportExportPublish.ImportCustomControlException: CustomControl with name failed to import with error: The import manifest file is invalid. XSD validation failed with the following error: ‘The import manifest file is invalid. XSD validation failed with the following error: ‘The ‘version’ attribute is invalid – The value ‘1.0’ is invalid according to its datatype ‘versionType’ – The Pattern constraint failed.’.”‘.” —> Microsoft.Crm.CrmException: The import manifest file is invalid. XSD validation failed with the following error: ‘The import manifest file is invalid. XSD validation failed with the following error: ‘The ‘version’ attribute is invalid – The value ‘1.0’ is invalid according to its datatype ‘versionType’ – The Pattern constraint failed.’.”‘.”at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.ValidateSchema()at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.Validate(ExecutionContext context)at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.Install() — End of inner exception stack trace — at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.Install()at Microsoft.Crm.Tools.ImportExportPublish.ImportCustomControlsHandler.ImportItem()

It is most likely due the version attribute being invalid. Make sure the version is 1.0.0 in your ControlManifest.Input.xml file

An undeclared property ‘new_bulkadjustment’ which only has property annotations in the payload but no property value was found in the payload.

Recently, I was running into an issue on xrm.webAPI.createRecord, when trying to update the lookup attribute to the entity object.

The oData naming convention for lookup attribute and the documentation around it asks you to use the schema name of the field with @odata.bind:

entity[“new_BulkAdjustment@odata.bind”] = “/new_revcontacts(00000000-0000-0000-a000-000d0a000a00)”;

This did not resolve the issue. I tried few other combinations using the REST builder, but unfortunately, nothing worked.

The way to set the lookup is:



new_BulkAdjustmnet is a lookup field on new_revcontact entity.