Getting Started with PCF controls: Create your first PCF control
It is just an extended version of Microsoft documentation Click to visit docs.
In this article, I’ll show you how to create a linear slider code component that lets users alter numerical values visually rather than by entering them manually into a column.
Prerequisites
Let’s get started
1.Create a Project
Open the CMD and move to the location where you want to create the project
cd <<Location Folder>>
mkdir LinearInput
2. Create a new component project by passing basic parameters
pac pcf init --namespace SampleNamespace --name LinearInputControl --template field
npm install
3.To generate ManifestDesignTypes.d.ts file
npm run refreshTypes
Open the project folder in VS code
4. Update the ControlManifest.Input.xml with below code
<?xml version="1.0" encoding="utf-8" ?>
<manifest>
<control namespace="SampleNamespace" constructor="LinearInputControl" version="1.1.0" display-name-key="LinearInputControl_Display_Key" description-key="LinearInputControl_Desc_Key" control-type="standard">
<type-group name="numbers">
<type>Whole.None</type>
<type>Currency</type>
<type>FP</type>
<type>Decimal</type>
</type-group>
<property name="controlValue" display-name-key="controlValue_Display_Key" description-key="controlValue_Desc_Key" of-type-group="numbers" usage="bound" required="true" />
<resources>
<code path="index.ts" order="1" />
<css path="css/LinearInputControl.css" order="1" />
</resources>
</control>
</manifest>
5. You need to create css folder inside LinearInputControl. After that you need to create LinearInputControl.css in css folder
6. Add the following code in css file.
.SampleNamespace\.LinearInputControl input[type=range].linearslider {
margin: 1px 0;
background:transparent;
-webkit-appearance:none;
width:100%;padding:0;
height:24px;
-webkit-tap-highlight-color:transparent
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider:focus {
outline: none;
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider::-webkit-slider-runnable-track {
background: #666;
height:2px;
cursor:pointer
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider::-webkit-slider-thumb {
background: #666;
border:0 solid #f00;
height:24px;
width:10px;
border-radius:48px;
cursor:pointer;
opacity:1;
-webkit-appearance:none;
margin-top:-12px
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider::-moz-range-track {
background: #666;
height:2px;
cursor:pointer
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider::-moz-range-thumb {
background: #666;
border:0 solid #f00;
height:24px;
width:10px;
border-radius:48px;
cursor:pointer;
opacity:1;
-webkit-appearance:none;
margin-top:-12px
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider::-ms-track {
background: #666;
height:2px;
cursor:pointer
}
.SampleNamespace\.LinearInputControl input[type=range].linearslider::-ms-thumb {
background: #666;
border:0 solid #f00;
height:24px;
width:10px;
border-radius:48px;
cursor:pointer;
opacity:1;
-webkit-appearance:none;
}
7. Update the index.ts file
import { IInputs, IOutputs } from "./generated/ManifestTypes";export class LinearInputControl implements ComponentFramework.StandardControl<IInputs, IOutputs> {
private _value: number;
private _notifyOutputChanged: () => void;
private labelElement: HTMLLabelElement;
private inputElement: HTMLInputElement;
private _container: HTMLDivElement;
private _context: ComponentFramework.Context<IInputs>;
private _refreshData: EventListenerOrEventListenerObject;public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement): void {
this._context = context;
this._container = document.createElement("div");
this._notifyOutputChanged = notifyOutputChanged;
this._refreshData = this.refreshData.bind(this);// creating HTML elements for the input type range and binding it to the function which refreshes the control data
this.inputElement = document.createElement("input");
this.inputElement.setAttribute("type", "range");
this.inputElement.addEventListener("input", this._refreshData);//setting the max and min values for the control.
this.inputElement.setAttribute("min", "1");
this.inputElement.setAttribute("max", "1000");
this.inputElement.setAttribute("class", "linearslider");
this.inputElement.setAttribute("id", "linearrangeinput");// creating a HTML label element that shows the value that is set on the linear range control
this.labelElement = document.createElement("label");
this.labelElement.setAttribute("class", "LinearRangeLabel");
this.labelElement.setAttribute("id", "lrclabel");// retrieving the latest value from the control and setting it to the HTMl elements.
this._value = context.parameters.controlValue.raw!;
this.inputElement.setAttribute("value", context.parameters.controlValue.formatted ? context.parameters.controlValue.formatted : "0");
this.labelElement.innerHTML = context.parameters.controlValue.formatted ? context.parameters.controlValue.formatted : "0";// appending the HTML elements to the control's HTML container element.
this._container.appendChild(this.inputElement);
this._container.appendChild(this.labelElement);
container.appendChild(this._container);
}public refreshData(evt: Event): void {
this._value = (this.inputElement.value as any) as number;
this.labelElement.innerHTML = this.inputElement.value;
this._notifyOutputChanged();
}public updateView(context: ComponentFramework.Context<IInputs>): void {
// storing the latest context from the control.
this._value = context.parameters.controlValue.raw!;
this._context = context;
this.inputElement.setAttribute("value", context.parameters.controlValue.formatted ? context.parameters.controlValue.formatted : "");
this.labelElement.innerHTML = context.parameters.controlValue.formatted ? context.parameters.controlValue.formatted : "";
}public getOutputs(): IOutputs {
return {
controlValue: this._value
};
}public destroy(): void {
this.inputElement.removeEventListener("input", this._refreshData);
}
}
Build your project
npm run build
Debugging your code component
npm start watch
Packaging your code components
1.Create a Solutions folder in current folder
mkdir Solutions
2.Move to Solutions folder
cd Solutions
3. Create a new solution project in the LinearInputControl folder
pac solution init --publisher-name Samples --publisher-prefix samples
4.Now, You need to refer to the location where the created component is located
pac solution add-reference --path ..\
Or
pac solution add-reference --path ..\..
You can try both which ever works for you.
Generate a zip file from your solution project
1.Run command in Solutions folder
msbuild /t:restore
2. Run MSbuild
msbuild
The generated solution zip file is located in the Solution\bin\debug
folder.
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
Follow me on Medium for more.