Use skybow Modern Forms to capture signatures on your SharePoint Modern List Forms. This can also be very useful if you want users to add their hand sketches to an item.
Do the following steps to get a signature field on your form.
- Add a new column of type Hyperlink or Picture with the name "Signature" to the list
- Add a new document library to the site to store the signatures and call it "Signatures"
- Modify the NewForm of your list with skybow Modern Forms
- Add a Rich Text control to the new/edit form and add the following content using the source editor
<p class="ms-Label sb-field-label">Sign here</p>
<div id="sigpad"> </div> - Add an After-Form Load action of type "Execute Script" on the same form.
- In the first part of the script we load some CSS styles to give the signature pad a border. After that in the second part, we load the Signature Pad JS library from Szymon Nowak.
Then in the third and last part we create a canvas and the signature pad which is added to the canvas. You can adjust the canvas width and height to your needs. Also the signature pad has some options which could be changed. Please check out the usage here: https://github.com/szimek/signature_pad#usage
Hint: The error in the code can be ignored at this time, since the SignaturePad-Object is not known to the editor as it is loaded dynamically some lines above.
Title: Render signature pad
Type: Execute Script
Script: 👇
var style = ".sigPad { border:1px solid black; border-radius: 5px; }";
jQuery('head').append("<style type='text/css'>"+style+"</style>");
//Source and usage: https://github.com/szimek/signature_pad#usage
var url = "https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js";
var fileName = "sigpadjs";
var moduleCache = window.module;
var defineCache = window.define;
window.module = undefined;
window.define = undefined;
window.SP.SOD.registerSod(fileName, url);
window.LoadSodByKey(fileName, null, true);
window.module = moduleCache;
window.define = defineCache;
var newCanvas =
jQuery('<canvas/>',{'class':'sigPad'})
.width(300)
.height(150);
jQuery('#sigpad').append(newCanvas);
var canvas = document.querySelector("canvas");
var signaturePad = new SignaturePad(canvas, {
minWidth: 0.5,
maxWidth: 1.5
});
window.signaturePad = signaturePad; - Save the action and add a button with actions to the form below the Rich Text control.
- Rename the button to "clear" and uncheck "is primary button"
- Add an Execute Script Action on this button to clear the signature pad.
Hint: The error in the code can be ignored at this time, since the signaturePad-Object is not known to the editor as it is loaded in the previously created form load action.
Title: Clear signature pad
Type: Execute Script
Script: 👇
signaturePad.clear();
- Extend the Save button in the command bar actions
- Add an Execute Script action to check if the pad is not empty.
Is the signature in your case just optional, just skip this step and go to the next.
General Info: A deferrer which gets rejected will stop all following actions to be executed
Title: Do not proceed if signature pad is empty
Type: Execute Script
Script: 👇var deferrer = jQuery.Deferred();
if(signaturePad.isEmpty()){
deferrer.reject("Please sign!");
}
else {
deferrer.resolve();
}
return deferrer.promise(); - Add another Execute Script action after the Save Form action to save the content from the signature pad as image in the document library created in Step 2.
Title: Save signature to library
Type: Execute Script
Script: 👇
var canvas = document.querySelector("canvas");
var BASE64_MARKER = ';base64,';
SaveToFile(canvas.toDataURL(),"signature-"+[[ID]]+".png",[[@Web.ServerRelativeUrl]]+"/Signatures");
function SaveToFile(content, filename, serverRelativeUrl) {
var ctx = new SP.ClientContext.get_current();
var createInfo = new SP.FileCreationInformation();
createInfo.set_content(new SP.Base64EncodedByteArray());
var arr = convertDataURIToBinary(content);
for (var i = 0; i < arr.length; ++i) {
createInfo.get_content().append(arr[i]);
}
createInfo.set_overwrite(true);
createInfo.set_url(filename);
this.files = ctx.get_web().getFolderByServerRelativeUrl(serverRelativeUrl).get_files();
ctx.load(this.files);
this.files.add(createInfo);
ctx.executeQueryAsync(function (s, e) {
}, function (sender, args) {
alert('Error saving signature: ' + args.get_message());
});
}
function convertDataURIToBinary(dataURI) {
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for (var i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
} - Add an Update List Item Action to set the signature picture column with the previously stored picture url
Title: Set signature on current item
Type: Update List Item
List: Choose the current list
List Item Id: =[[ID]]
Signature field: 👇[[=window.location.origin]][[@Web.GetFirstValueForQuery([[@Web.ServerRelativeUrl]]+'/Signatures', '<Where><Eq><FieldRef Name="FileLeafRef" /><Value Type="Text">signature-[[ID]].png</Value></Eq></Where>', 'FileRef')]]