Submit Ink Signatures with a Form

This guide outlines how to submit ink signatures along with a form that’s submitted.

Ink signatures aren’t part of the signature form field properties; they’re just ink annotations that overlap the signature form field and thus are considered ink signatures. Therefore, by default, they’re not included in the payload that’s sent when a form is submitted.

However, you can store ink signature data as a string in a hidden text form field. When the form is submitted, the string will then be sent along with the rest of the form data.

This is how you could retrieve the signatures for the corresponding form fields:

async function getStringifiedInkSignatures(instance) {
  let stringifiedSignatures = {};
  const pagesPromises = Array.from({
    length: instance.totalPageCount
  }).map((_, index) => {
    return instance.getAnnotations(index);
  });
  const annotationsByPage = await Promise.all(pagesPromises);
  const inkSignatureAnnotations = annotationsByPage.reduce(
    (acc, pageAnnotations) => {
      const pageInkSignatureAnnotations = pageAnnotations.filter(
        (annotation) => annotation.isSignature
      );
      return pageInkSignatureAnnotations.size > 0
        ? acc.concat(pageInkSignatureAnnotations.toArray())
        : acc;
    },
    []
  );
  const formFields = await instance.getFormFields();
  const signatureWidgetAnnotations = annotationsByPage.reduce(
    (acc, pageAnnotations) => {
      const pageWidgetAnnotations = pageAnnotations.filter(
        (annotation) => annotation.formFieldName
      );
      const pageSignatureWidgetAnnotations = pageWidgetAnnotations.filter(
        (annotation) =>
          formFields.find(
            (formField) =>
              formField.name === annotation.formFieldName &&
              formField instanceof
                PSPDFKit.FormFields.SignatureFormField
          )
      );
      return pageSignatureWidgetAnnotations.size > 0
        ? acc.concat(pageSignatureWidgetAnnotations.toArray())
        : acc;
    },
    []
  );
  inkSignatureAnnotations.forEach((inkSignatureAnnotation) => {
    const inkSignatureWidgetAnnotation = signatureWidgetAnnotations.find(
      (signatureWidgetAnnotation) => {
        return signatureWidgetAnnotation.boundingBox.isRectOverlapping(
          inkSignatureAnnotation.boundingBox
        );
      }
    );
    if (inkSignatureWidgetAnnotation) {
      stringifiedSignatures[
        inkSignatureWidgetAnnotation.formFieldName
      ] = JSON.stringify(inkSignatureAnnotation.toJS());
    }
  });
  return stringifiedSignatures;
}

To submit this information as part of the form, the PDF document needs to have an additional hidden text form field for each signature form field in the document. You can create it on the fly if you have the Form Creator component in your license.

Then you can call the following function just before submitting the form. For example, you can name these form fields with the pattern "inksignature*for*[signature form field name here]":

async function submitForm() {
  let stringifiedInkSignaturesFormFieldValues = {};
  const stringifiedInkSignatures = await getStringifiedInkSignatures(
    instance
  );
  Object.entries(stringifiedInkSignatures).forEach(
    ([formFieldName, stringifiedInkSignature]) => {
      stringifiedInkSignaturesFormFieldValues[
        `inksignature_for_${formFieldName}`
      ] = stringifiedInkSignature;
    }
  );
  instance.setFormFieldValues(stringifiedInkSignaturesFormFieldValues);
  // Now submit the form!
}

This has been tested with PSPDFKit for Web 2020.2.3