Close Canvas App window using PCF button

Canvas Apps can be launched from within the Dynamics CE using a ribbon button and calling a javascript funtion to open the Canvas App in a new window using window.open.

However, once a Canvas app window is launched, you can’t close the window. Microsoft provides Exit() and Exit(true) functions. Exit() navigates away from the current page and redirects to the list of canvas apps, while Exit(true) signs out the user and navigates to the login page. In either case, the window should be closed manually by the user.

I found a way to close this window using PCF button embedded within a canvas app. This a two step process:

  1. Creating and deploying PCF button control to the Dynamics CE/CDS/Dataverse environment
  2. Adding this PCF button control to the Canvas App
  1. Creating and deploying the PCF button control to the Dynamics CE environment:

You can follow this blog to create and deploy the PCF button control with one additional changes. In the submitClicked(event:Event) handler, add the following code

2. Adding the PCF button control to the Canvas App

To enable PCF control to be used within the Canvas App, you need to:

  • Enable power apps component framework for canvas app in the power platform admin center
  • Enable Components in Preview Features of the Canvas App settings

Enable power apps component framework for canvas app in the power platform admin center

  • Go to admin.powerplatform.microsoft.com
  • Select the Environment where you want to embed the PCF control
  • Click Settings -> Product -> Features
  • Enable the Power Apps component framework for canvas apps

The next step is to Enable Components in Preview Features of the Canvas App settings

  1. Open the canvas app
  2. Select File -> Settings -> Advance Settings
  3. Under Preview Features -> Enable Components

Now that the PCF control components is enabled for your CDS/Dataverse environment and the Canvas App, let’s embed this control in your Canvas App.

  • Go to the canvas App
  • Select the Insert tab -> Custom -> Import component
  • You will notice two tabs, Canvas and Code. Select the “Code” tab
  • Select your PCF control (this is visible only if your pcf control is deployed to this CDS environment, see step 1 – creating and deploying the pcf control) from the list, and click on Import
  • Importing this component will enable the Code components section in your Insert tab in the left navigation and display your PCF control
  • Drag this control across to your Canvas App
  • Save and Publish

Test this out by opening the canvas app from the ribbon button. Now, clicking on this button should close the Canvas App.

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

this._eleMainContainer.appendChild(this._eleButton);
this._container.appendChild(this._eleMainContainer);

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

.canvasAppButton
{
    background-color:#2d5297;
    color:white;
    width:150px;
    height:40px;
    border-radius: 8px;
    border-color:transparent;
    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!!

Deployment:

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 Solution.zip 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.