Bhubaneswar, Odisha, India
+91-8328865778
support@softchief.com

PCF Control – Develop a React Rating Control for your Power Apps

PCF Control – Develop a React Rating Control for your Power Apps

In this blog you will understand how to develop a React component to render a Rating control for your power apps.

Follow these steps to learn:

Watch the video below to learn step by step or scroll down to read the article.

Get the source code from here. https://github.com/softchief/PCFControlsReactRating

Step 1: Inititate Project

Scenario:

In a Customer Service portal built on Dynamics 365 or Power Apps, after resolving a customer case, you want to collect customer feedback by allowing them to rate the service they received. This rating will be visually displayed as stars, and the customer can select a rating from 1 to 5 stars.

This rating component will be reusable across various case records and update the customer feedback directly in the Dataverse. It also allows users to change their rating if needed.

How to Implement It:

  • PCF Control: A React-based PCF control will display a set of stars (1 to 5) and allow the user to click a star to rate the service.
  • Integration: The component will be integrated with Dataverse to read and update the rating field for a specific case.
  • Dynamic Behavior: The component will render dynamically based on the case’s current rating and provide visual feedback on hover (e.g., highlighting the selected stars).

Create a PCF Project: Open Visual Studio Code -> Terminal Command Prompt and hit below command.

pac pcf init --namespace FeedbackControl --name RatingControl --template field
cd RatingControl
npm install

Add React Dependencies: Install React and related libraries:

npm install react react-dom

Create React Component for Rating Control: create a new file in project called MyRatingComponent.tsx and use below code.

import * as React from "react";

interface IProps {
    value: number;
    onChange: (newValue: number) => void;
}

const MyRatingComponent: React.FC<IProps> = ({ value, onChange }) => {
    const [hoverValue, setHoverValue] = React.useState<number | null>(null);

    const handleClick = (rating: number) => {
        onChange(rating);
    };

    return (
        <div style={{ display: 'flex' }}>
            {[1, 2, 3, 4, 5].map(star => (
                <span
                    key={star}
                    onMouseEnter={() => setHoverValue(star)}
                    onMouseLeave={() => setHoverValue(null)}
                    onClick={() => handleClick(star)}
                    style={{
                        cursor: 'pointer',
                        fontSize: '24px',
                        color: (hoverValue || value) >= star ? 'gold' : 'gray',
                    }}
                >

                </span>
            ))}
        </div>
    );
};

export default MyRatingComponent;

Update index.ts to render the component and handle updates from Power Apps:

import { IInputs, IOutputs } from "./generated/ManifestTypes";
import * as React from "react";
import * as ReactDOM from "react-dom";
import MyRatingComponent from "./MyRatingComponent";

export class RatingControl implements ComponentFramework.StandardControl<IInputs, IOutputs> {
    private container: HTMLDivElement;
    private rating: number;

    // Initialize control
    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement): void {
        this.container = container;
        this.rating = context.parameters.ratingField.raw || 0;
        this.renderControl(context, notifyOutputChanged);
    }

    // Update control on data change
    public updateView(context: ComponentFramework.Context<IInputs>): void {
        this.rating = context.parameters.ratingField.raw || 0;
        this.renderControl(context);
    }

    private renderControl(context: ComponentFramework.Context<IInputs>, notifyOutputChanged?: () => void): void {
        ReactDOM.render(
            React.createElement(MyRatingComponent, {
                value: this.rating,
                onChange: (newValue: number) => {
                    this.rating = newValue;
                    notifyOutputChanged && notifyOutputChanged();
                }
            }),
            this.container
        );
    }

    // Output the rating to update in Dataverse
    public getOutputs(): IOutputs {
        return { ratingField: this.rating };
    }

    // Cleanup when control is removed
    public destroy(): void {
        ReactDOM.unmountComponentAtNode(this.container);
    }
}

Build and Deploy the solution: use below script.

mkdir Solutions
cd Solutions
pac solution init --publisher-name developer --publisher-prefix dev
pac solution add-reference --path c:\downloads\mysamplecomponent
msbuild /t:build /restore - in DEV CMD
pac auth create --url https://xyz.crm.dynamics.com
pac auth list
pac auth select --index <index of the active profile>
pac pcf push --publisher-prefix <your publisher prefix>

Hope it helps.