From Field to Functionality: Creating a Button-Enhanced PCF Control
Introduction
From Field to Functionality: Creating a Button-Enhanced PCF Control

Introduction
In the world of Power Apps, sometimes default field controls just don’t cut it. In this tutorial-style blog, we’ll explore how to create a Power Apps Component Framework (PCF) control that adds a button to a numeric field — specifically, an age field that increments and decrements when clicked.
This guide is ideal for beginners to PCF and covers the entire journey: from manifest setup to deploying your control in a model-driven app.
Why This Use Case?
Buttons aren’t native to input fields in Dataverse forms. By creating a PCF control, we:
- Enhance user experience with an intuitive UI.
- Learn the PCF lifecycle.
- Understand binding data and deploying to model-driven apps.
Step 1: Prerequisites
Ensure you have the following installed:
- Node.js (more than version 14.0)
- Power Platform CLI (
pac) - Visual Studio (with MSBuild)
- Power Apps environment with a Model-Driven App
Install the PCF project template globally:
npm install -g pac pcf-scripts
Step 2: Create the PCF Control
pac pcf init --namespace MyNamespace --name AgeIncremental --template field
cd AgeIncremental
npm install
Here we are going to create an age field with increment and decrement buttons, We need to modify the generated ControlManifest.Input.xml file property with the relevant datatype accordingly:
<property name="sampleProperty" display-name-key="Property_Display_Key" description-key="Property_Desc_Key" of-type="Whole.None" usage="bound" required="true" />
Step 3: Write the TypeScript Logic
In index.ts, update the class to render the field with both + and - buttons:
import { IInputs, IOutputs } from "./generated/ManifestTypes";
export class numberControl implements ComponentFramework.StandardControl<IInputs, IOutputs> {
private _input: HTMLInputElement;
private _notifyOutputChanged: () => void;
private _container: HTMLDivElement;
private _value: number;
constructor() {
// Empty
}
public init(
context: ComponentFramework.Context<IInputs>,
notifyOutputChanged: () => void,
state: ComponentFramework.Dictionary,
container: HTMLDivElement
): void {
this._value = context.parameters.sampleProperty.raw ?? 0;
this._notifyOutputChanged = notifyOutputChanged;
this._container = container;
this._input = document.createElement("input");
this._input.type = "number";
this._input.value = this._value.toString();
this._input.style.margin = "0 8px";
this._input.onchange = () => {
this._value = parseInt(this._input.value) || 0;
this._notifyOutputChanged();
};
const incrementButton = document.createElement("button");
incrementButton.textContent = "+";
incrementButton.onclick = () => {
this._value++;
this._input.value = this._value.toString();
this._notifyOutputChanged();
};
const decrementButton = document.createElement("button");
decrementButton.textContent = "-";
decrementButton.onclick = () => {
this._value--;
this._input.value = this._value.toString();
this._notifyOutputChanged();
};
this._container.appendChild(decrementButton);
this._container.appendChild(this._input);
this._container.appendChild(incrementButton);
}
public updateView(context: ComponentFramework.Context<IInputs>): void {
const newValue = context.parameters.sampleProperty.raw ?? 0;
if (newValue !== this._value) {
this._value = newValue;
this._input.value = this._value.toString();
}
}
public getOutputs(): IOutputs {
return {
sampleProperty: this._value
};
}
public destroy(): void {
// Optional cleanup code
}
}
Step 4: Build and Package
npm run build
mkdir Solution
cd Solution
pac solution init --publisher-name developer --publisher-prefix dev
pac solution add-reference --path "../" (use the full path of the project)
# From inside the Solution folder:
msbuild /t:Restore
msbuild
Find the solution .zip under bin\Debug.
Step 5: Import into Power Apps
- Navigate to make.powerapps.com.
- Go to Solutions > Import.
- Upload the
.zipfile. - Open your Model-Driven form.
- Select your field (bound to
sampleProperty) > Click Change Control > Add your PCF control.
Output:

Common Issues and Fixes
❌ Control Not Showing in “Change Control” List
- Ensure your property has
usage="bound". - The field type in Dataverse must match the type in the manifest.
- You must import it via a solution, not just build locally.
❌ TypeScript Errors: Property 'sampleProperty' does not exist on type 'IInputs'
- Your manifest defines the property. Run
npm run buildagain to regenerate typings.
❌ MSBuild Not Found
- Ensure Visual Studio is installed with the .NET Desktop Build Tools.
- Use the Developer Command Prompt or install MSBuild standalone.
With just a bit of TypeScript and XML, we’ve created a more interactive input field using PCF. This blog demonstrated how to bind a property and use simple UI logic for a + and — button.
메타데이터
- post_id
- c7aebf7dfde4
- slug
- from-field-to-functionality-creating-a-button-enhanced-pcf-control-c7aebf7dfde4
- url
- https://medium.com/@shakishnavi27/from-field-to-functionality-creating-a-button-enhanced-pcf-control-c7aebf7dfde4
- canonical_url
- https://medium.com/@shakishnavi27/from-field-to-functionality-creating-a-button-enhanced-pcf-control-c7aebf7dfde4
- author_url
- https://medium.com/@shakishnavi27
- status
- ok
- fetched_at
- 2026-06-12 22:02:08