In this article. I have explained how to develop QRCode Generator in SharePoint using SPFx
What is QR Code?
- It is a machine-scannable image that can instantly be read using a Smartphone camera
- QR code consists of a number of black squares and dots which represent certain pieces of information.
Webpart Features
- Generate QRCode based on information like Plain Text and URL.
- Download the generated QRCode to your local computer.
- If needed you can store the generated QRCode information to SharePoint list.
Create a new project folder project name "QRCodeGeneratorApp" from the command window
![]()
Provide the solution name "QR Code Generator” and choose the client side to component to create as “Webpart”
![]()
Provide the webpart name and choose “React” as a project template
![]()
After successful creation of SharePoint project install necessary NPM packages
Open the terminal enter "npm install --save qrcode” “npm install @pnp/sp”
![]()
![]()
Open the “QRCodeGenerator.tsx” from src/webparts/components Include the below imports for QRCode & PNP JS to connect SharePoint REST API
![]()
Create SharePoint custom list to store the QRCode Information
![]()
![]()
![]()
Next open Visual studio code IDE open the file “QRCodeGenerator.tsx”
Create the Interface to pass the parameters for store the QRCode data into SharePoint lists
Create a constant variable to store the List Name and initialize the SP using spfi
export interface IQRCodeApp {
Title: string,
QRInformation: string,
}
const ListName = "QRCodeApp"
const sp = spfi().using(SPBrowser({ baseUrl: "<!—Sharepoint site URL" }));
Declare the necessary State Variables
//Declare all the necessary State variables
//Store the Base64 URL from canvas element
const [baseURL, SetbaseURL] = useState(String);
//Store the QRCode data information simple text
const [title, SetTitle] = useState(String);
//Handle disabled event for save/download/generate/clear input controls
const [saveDisabled, setSaveDisabled] = useState(true);
const [downloadDisabled, setDownloadDisabled] = useState(true);
const [generateDisabled, setGenerateDisabled] = useState(true);
const [clearDisabled, setClearDisabled] = useState(true);
//Manage success / Error Message
const [successMessage, setSuccessMessage] = useState(false);
const [errorMessage, setErrorMessage] = useState(false);
Create a function “GenerateQRCode” to generate QRCode based on the input,
//Generate the QR Code
const GenerateQRCode = () => {
QRCode.toCanvas(document.getElementById('myCanvas'), title).then(res => {
let canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
let dataURL = canvas.toDataURL();
SetbaseURL(dataURL);
setSaveDisabled(false);
setDownloadDisabled(false);
setGenerateDisabled(true);
console.log(res);
}).catch(err => {
console.log(err);
})
}
Create a function “Download” to download the generate QRCode information locally on “Download” onclick event
//Handles download generated QRCode
const Download = () => {
let canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
const dataURL = canvas.toDataURL();
let a = document.createElement("a"); //Create <a>
a.href = "" + dataURL; //Image Base64 Goes here
a.download = "QRCode.png"; //File name Here
a.click();
setDownloadDisabled(true);
}
Create a function for handling success/error message
/* Success Messsage Handler */
const SuccessMessage = () => (
<MessageBar
messageBarType={MessageBarType.success}
isMultiline={false}
>
QRCode Saved Successfully !..
</MessageBar>
);
/* Error Messsage Handler */
const ErrorMessage = () => (
<MessageBar
messageBarType={MessageBarType.error}
isMultiline={false}
>
Oops Something went wrong !..
</MessageBar>
);
Create a function to clear the input & canvas element using Onclick event on “Clear” button
//Clear all the inputs
const clearValues = () => {
let titleValue: string = '';
SetTitle(titleValue);
setGenerateDisabled(false);
setClearDisabled(true);
setDownloadDisabled(true);
setSaveDisabled(true);
clearCanvas();
}
//Clear the canvas element
const clearCanvas = () => {
let canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
let context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var w = canvas.width;
canvas.width = 1;
canvas.width = w;
}
Create a function to store the QRCode information into SharePoint list on “Save” onclick event
const SaveItem = async () => {
if (!_.isEmpty(title)) {
try {
let params: IQRCodeApp = {
Title: title,
QRInformation: baseURL
}
console.log(params);
const saveItems: any = await sp.web.lists.getByTitle(ListName).items.add(params);
if (saveItems) {
setSuccessMessage(true);
setSaveDisabled(true);
} else {
setErrorMessage(true);
}
} catch (error) {
setErrorMessage(true);
}
} else {
ErrorMessage()
setErrorMessage(true);
}
}
Use a Stack control to render the input element like below.
Below style variable to manage the width of the stack and handles padding of stack element
/* Styles For Stack Controls */
const stackItemStyles: IStackItemStyles = {
root: {
width: 600
},
};
const innerStackTokens: IStackTokens = {
childrenGap: 5,
padding: 10,
};
return (
<Stack>
<Stack horizontal tokens={innerStackTokens}>
<Stack.Item styles={stackItemStyles}>
<TextField multiline rows={3} value={title} onChange={onChangeInput} />
</Stack.Item>
</Stack>
<Stack horizontal tokens={innerStackTokens}>
<Stack.Item >
<PrimaryButton text="Generate" disabled={generateDisabled} onClick={GenerateQRCode} />
</Stack.Item>
<Stack.Item>
<PrimaryButton text="Clear" disabled={clearDisabled} onClick={clearValues} />
</Stack.Item>
</Stack>
<Stack horizontal >
<Stack.Item> <canvas id="myCanvas"></canvas> </Stack.Item>
</Stack>
<Stack horizontal >
<StackItem><PrimaryButton text="Download" disabled={downloadDisabled} onClick={Download} /> <PrimaryButton text="Save" disabled={saveDisabled} onClick={SaveItem} /></StackItem>
</Stack>
<Stack horizontal tokens={innerStackTokens}>
{(successMessage) && <SuccessMessage></SuccessMessage>}
{(errorMessage) && <ErrorMessage></ErrorMessage>}
</Stack>
</Stack>
)
Full Source Code of "QRCodeGenerator.tsx"
import React, { useState, useEffect, FC } from 'react';
import styles from './QrCodeGenerator.module.scss';
import { IQrCodeGeneratorProps } from './IQrCodeGeneratorProps';
import { escape, isElement } from '@microsoft/sp-lodash-subset';
import { IStackItemStyles, IStackTokens, PrimaryButton, Stack, StackItem, TextField, Dialog, MessageBar, MessageBarButton, MessageBarType, Link } from 'office-ui-fabric-react';
import * as QRCode from 'qrcode';
import { spfi, SPBrowser } from '@pnp/sp';
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import _ from 'lodash';
export interface IQRCodeApp {
Title: string,
QRInformation: string,
}
const ListName = "QRCodeApp"
const sp = spfi().using(SPBrowser({ baseUrl: "https://wh1r2.sharepoint.com/" }));
export const QrCodeGenerator: FC<IQrCodeGeneratorProps> = (props) => {
//Declare all the necessary State variables
const [baseURL, SetbaseURL] = useState(String);
const [title, SetTitle] = useState(String);
const [saveDisabled, setSaveDisabled] = useState(true);
const [downloadDisabled, setDownloadDisabled] = useState(true);
const [generateDisabled, setGenerateDisabled] = useState(true);
const [clearDisabled, setClearDisabled] = useState(true);
const [successMessage, setSuccessMessage] = useState(false);
const [errorMessage, setErrorMessage] = useState(false);
//OnChange handler for Multiline input
const onChangeInput = (ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string) => {
SetTitle(newValue);
setGenerateDisabled(false);
setClearDisabled(false);
if (newValue == '') {
setGenerateDisabled(true);
setClearDisabled(true);
}
}
//Generate the QR Code
const GenerateQRCode = () => {
QRCode.toCanvas(document.getElementById('myCanvas'), title).then(res => {
let canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
let dataURL = canvas.toDataURL();
SetbaseURL(dataURL);
setSaveDisabled(false);
setDownloadDisabled(false);
setGenerateDisabled(true);
console.log(res);
}).catch(err => {
console.log(err);
})
}
//Handles download generated QRCode
const Download = () => {
let canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
const dataURL = canvas.toDataURL();
let a = document.createElement("a"); //Create <a>
a.href = "" + dataURL; //Image Base64 Goes here
a.download = "QRCode.png"; //File name Here
a.click();
setDownloadDisabled(true);
//SetbaseURL(baseURL);
}
/* Success Messsage Handler */
const SuccessMessage = () => (
<MessageBar
messageBarType={MessageBarType.success}
isMultiline={false}
>
QRCode Saved Successfully !..
</MessageBar>
);
/* Error Messsage Handler */
const ErrorMessage = () => (
<MessageBar
messageBarType={MessageBarType.error}
isMultiline={false}
>
Oops Something went wrong !..
</MessageBar>
);
//Save QRCode Information to SharePoint List
const SaveItem = async () => {
if(!_.isEmpty(title)){
try {
let params: IQRCodeApp = {
Title: title,
QRInformation: baseURL
}
console.log(params);
const saveItems: any = await sp.web.lists.getByTitle(ListName).items.add(params);
if (saveItems) {
setSuccessMessage(true);
setSaveDisabled(true);
} else {
setErrorMessage(true);
}
} catch (error) {
setErrorMessage(true);
}
} else{
ErrorMessage()
setErrorMessage(true);
}
}
//Clear all the inputs
const clearValues = () => {
let titleValue: string = '';
SetTitle(titleValue);
setGenerateDisabled(false);
setClearDisabled(true);
setDownloadDisabled(true);
setSaveDisabled(true);
clearCanvas();
}
//Clear the canvas element
const clearCanvas = () => {
let canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
let context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var w = canvas.width;
canvas.width = 1;
canvas.width = w;
}
/* Styles For Stack Controls */
const stackItemStyles: IStackItemStyles = {
root: {
width: 600
},
};
const innerStackTokens: IStackTokens = {
childrenGap: 5,
padding: 10,
};
return (
<Stack>
<Stack horizontal tokens={innerStackTokens}>
<Stack.Item styles={stackItemStyles}>
<TextField multiline rows={3} value={title} onChange={onChangeInput} />
</Stack.Item>
</Stack>
<Stack horizontal tokens={innerStackTokens}>
<Stack.Item >
<PrimaryButton text="Generate" disabled={generateDisabled} onClick={GenerateQRCode} />
</Stack.Item>
<Stack.Item>
<PrimaryButton text="Clear" disabled={clearDisabled} onClick={clearValues} />
</Stack.Item>
</Stack>
<Stack horizontal >
<Stack.Item> <canvas id="myCanvas"></canvas> </Stack.Item>
</Stack>
<Stack horizontal >
<StackItem><PrimaryButton text="Download" disabled={downloadDisabled} onClick={Download} /> <PrimaryButton text="Save" disabled={saveDisabled} onClick={SaveItem} /></StackItem>
</Stack>
<Stack horizontal tokens={innerStackTokens}>
{(successMessage) && <SuccessMessage></SuccessMessage>}
{(errorMessage) && <ErrorMessage></ErrorMessage>}
</Stack>
</Stack>
)
}
export default QrCodeGenerator;
Hit “gulp serve” to run the SPFx component in workbench
![]()