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