Category Archives: TypeScript

React – Extended boundary of PowerApps Component Framework

Published / by AK / Leave a Comment

In previous post I demonstrated about how to use React with the former version of PowerApps Component Framework (PCF) by modifying PCF packages, which is unsupported.

I am a strong believer that plain old JavaScript is a not a good choice when it comes to building moderately complex component that use DataSets, and as such, since day one, I have been looking forward to Microsoft officially supporting React in PowerApps Component Framework.

Recently, the Microsoft PCF team finally announced their official support of React with PCF and released an example on how to achieve it. To my surprise, the approach I described in my previous blog post was conceptually similar to theirs.

I personally feel Microsoft’s example is too complex to understand to someone who is not familiar with React.

In this post I am going to explain how to use React in PowerApps Component Framework, through a step-by-step explanation, using a very basic component, a text box. This blog post is intended to those developers who are not familiar with React.

React 

React is a JavaScript library for building user interfaces. You can learn about it at https://reactjs.org/docs/getting-started.html

Principle

Skipping the basic steps, below are the 3 React principles you need to be familiar with

  1. Components – Components let you split the UI into independent, reusable elements, and force you to think about each element in isolation. Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.
  2. Props – Props are immutable and therefore read-only. A component must never modify its own props.
  3. State – A state can be local or encapsulated. It is not accessible to any component other than the one that owns and sets it.

For example, you can create a component and assign it some props by the caller. The component will then manage its own state.

React is designed for “top-down” or “unidirectional” data flow.

A picture is worth a thousand words

Before we start, I would like to present the following diagram. It summarises the concept of using React in PCF.

PCF component will pass the Input value and a custom function (in this example, it is notifyChange) to React component via Props. In React component, we will copy Props into State in componentWillReceiveProps. Now, we can make changes to the State value in React component. When we decide to send the value from PCF, we will call the function notifyChange which will then signal its new value to PCF.

Based on this diagram, we are going to build a simple text box using React.

Build a simple text box without React

You can follow Microsoft documentation to create a PCF project. Once you open it in Visual Studio Code, let’s create a sample text box using TypeScript. You can find the sample code for this step here.

Principle #1 and creating a React component

To create a React component, let’s create a new file called ReactSampleTextBox.tsx, and add the code from here. In render() function, we are creating an input text.

Now, go back to index.ts and render the ReactSampleTextBox component. Code can be found here.

We will start to see the benefit of using React. Your index.ts becomes much cleaner. You will see an input text from React component when you run the component. Please note we are here to create a simple React component without passing any data from the PCF component.

Principle #2 and passing data

In PCF, this principle is about passing data from PCF to the custom React component. However, the principle states that we must use Props to pass the data to our custom React component and that it must remain read-only. But, since we have States, we use componentWillReceiveProps to set the value of Props to State.

Now, it’s time to modify index.ts and ReactSampleTextBox.tsx for passing data.

First, in ReactSampleTextBox.tsx, we need to declare an Interface for props. Let’s call it IProps and it has a property called value. We will use this value property to pass data from PCF to React component. Your ReactSampleTextBox.tsx will look like following. The value property of the input text is bound to props value of React component

In index.ts, declare an object props whose type is IProps from ReactSampleTextBox, assign the value in updateView and pass it to React component on rendering.

When you test the control, you will see the input text in React component will show any value you change via Inputs panel. However, you will NOT be able to directly edit any value in React text box. This is because we don’t tell the input text what to do. Let’s modify ReactSampleTextBox.tsx as following. Here, we create handleChange function, bind it in constructor and bind it onChange event of the input text.

First, let’s create IState interface. And copy the props value into the state in both constructor and componentWillReceiveProps. Next, we create handleChange function and bind it to the input text. Now, if you run the component, you will be able to pass value to React component from Inputs panel and you will be able to change value in text box.

You will notice any value change in React component text box will NOT show in Outputs panel.

Principle #3 and its problem

In the PCF example the third principle is about passing data from custom React component back to PCF. Since React is “unidirectional” how do we pass data from our React component back to PCF?

When using React for pages rendering purposes, a unidirectional data flow is not a problem. We tend to send data to the server-side using HTML Forms and re-render the page.

This could be troublesome with PCF as we have to use notifyOutputChanged in the init method to notify PowerApps Forms that the value has been changed in the component.

Getting around with the third principle issue

To get around this issue, we need to create a notifyChange function, which will update the output value of PCF and call the notifyOutputChanged in our PCF component.

We can pass the notifyChange function to our custom React component as part of props. Whenever a value is updated in our React component, the notifyChange function is executed, which will subsequently call notifyOutputChanged to update the output value and subsequently trigger onChange event on PowerApps Form.

Let’s make small changes to ReactSampleTextBox.tsx by adding onChange property in IProps. Now, when handleChange is executed, we will execute onChange function from props.

Now, back to index.ts. Create a new function called notifyChange which will then call notifyOutputChange.

The last thing to do is to pass notifyChange from index.ts to ReactSampleTextBox as props.

Run it to enjoy React component in PCF. The code can be found here.

I agree this type of component can be done without React. My intention, however, is to explain how values are passed between PCF and React component, and I believe building a very simple component is the best approach to explain the whole process.

If you are hard-core React developer, you might want to use redux to manage the state in a clean way. Field template component will unlikely require redux. However, if you are building a complex dataset component, not only for display but also for CRUD, redux is worth to check out.

Hopefully this post has been helpful to anyone beginning their adventure with React in PCF.

PowerApps Component Framework – Beyond the boundary

Published / by AK / 1 Comment on PowerApps Component Framework – Beyond the boundary

Note: I am going to write some dark magic with PCF. It is not currently supported by Microsoft. These are my personal findings. Views are my own. But if you want to dismantle PCF and want to test the boundary, then read further.

Credit: Andrew Ly for his Number Button Selector control and feedback. Rami Mounla for proofread and correction on the content.

The source code can be downloaded at my github.

Intro

Microsoft has announced public preview of PowerApps Component Framework (PCF) and its Command Line Interface (CLI) in April 2019. Many developers, including me, have been anticipating this new feature. I find the documentation useful. A few people has started building and sharing new controls. No disappointment from this beautiful community.

Absolute need

TypeScript. Although I am not absolutely convinced the preference of TypeScript to JavaScript (by the way, JavaScript is my favorite), it is the only choice we have right now. However, Andrew Ly has pointed out essential areas where TypeScript really shines, such as strong typing, OO concepts thus bringing the gap between JavaScript and OO languages like C#/Java.

Beyond absolute need

There is no doubt you can build any control following Microsoft documentation. But, I don’t want to stop here. I want to push its boundary and limits. So far, I recommend adding 3 more types of knowledge.

2. React for UI components

When the sample from Microsoft documentation shows building the UI using TypeScript, it reminds me of my student days when I had an assignment task asking to build a UI in C++. I could not force myself to create UI in C++ program.

TypeScript for building modern UI? No, please.

I admit I was super lazy during my student life. I only wanted to deliver bare minimum. So, UI in code file is a NO for me. However, as my career began and I collected some experience, I allegedly become a bit wiser. Yet, the wiser me supports the lazy me.

There are many libraries to choose. However, you can find react and react-dom packges under node_modules after executing “npm install” at step 4.. So, React is the choice. You can also use JSX which makes life easier when building DOMs.

2. NPM for packages

The motto of “Why reinvent the wheel?”. NPM hosts thousands of free packages. Most of the well-established libraries are now distributing over NPM. It is like NuGet for JavaScript. Now, you may ask “why not reference the CDN?”. Well, that brings me to next one.

3. Webpack for bundling

A module bundler. It will bundle all your resources, and packages from NPM, as a single package. Referring to CDN will only work when there is connectivity (or it is dependency). If we want to use it offline in mobile devices, we may encounter some issues.

The good news is that you don’t need to worry about NPM and webpack. PCF CLI handles them gracefully in most cases. I did however notice that there are some issues with adding large NPM packages (>500kb). The bundling tends to behave weirdly.

Create a new PCF Project

You use “pac pcf init” command to create a new PCF project. It will pre-create ControlManifest.Input.xml and index.ts.

pac pcf init
pac pcf init

Create a react component

Let’s create DemoComponent.tsx and write some scripts. The sample source can be found at my github repository.

Project structure
Project structure

Run ‘npm run build’ command. You will get an error saying ‘–jsx’ is not set. To resolve this, you need to add “jsx”: “react” in tsconfig.json located under your root folder. After this, you will be able to run ‘npm run build’ command without any issue.

JSX error
JSX error
Update tsconfig.json
Updating tsconfig.json

Now, let’s render DemoControl in index.ts. You will see an error and you will not be able to run ‘npm run build’ command.

Render react component

Now, let’s change index.ts to index.tsx and you will see the error is gone from IDE. You also need to update the code file extension in ControlManifest.Input.xml.

But, when you run ‘npm run build’, you run into another issue saying ‘Code file needs to be a typescript (.ts)’.

Looking at the error, it comes from pcf-scripts module which is located under node_modules folder in your PCF project.

tsx error during build
tsx error

A quick search using the error message brings me to line 84 at controlcontext.js under pcf-scripts module.

Include tsx
Only allow .ts

You simply need to update ‘if’ statement to allow .tsx extension and save it. And Magic happens.

Include tsx
Add .tsx into file type

Now, if you run ‘npm run build’, it will succeed. Next, it’s time to execute ‘npm start’. When the browser is launched, you will see the error ‘React’ is not defined.

React error
React error

To address this error, open index.html under your pcf root folder\node_modules\pcf-start and add following two script tags.

<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

As soon as you save your changes, your react component will be rendered.

React control demo

Congratulations! You have created a custom control using PCF and React.

The proceder in this article is experimental only.

Final word

Even though you can deploy React control to model-driven app, this approach is not currently supported by Microsoft. I am sharing this only for experimental purposes and showing how PCF can be extended using modern libraries. I am not a pro-React developer nor a TypeScript developer, therefore, I may have approached this the wrong way. If you have any comments, please share them below.