Common pattern: signatures + attachments

Capture a signature and a supporting document on the same form, and have both persist correctly through the post-save phase.

Inspection forms, consent forms, and delivery receipts all need the same combo: a signature, plus a supporting attachment (a photo, a receipt PDF, an audit document). Both write in the post-save phase, so the recipe is more interesting than it looks.

The data

In your SharePoint list:

  • An Image column for the signature (e.g. CustomerSignature)
  • The built-in Attachments (every list has this; no column to add)

On your form:

The save flow

Both fields write in the post-save phase:

  1. Pre-flight, validation, onBeforeSave
  2. Primary write, the SP item is created
  3. Post-save phase:
    • Signature uploads PNG to the Image column
    • Attachments uploads files to the SP Attachments endpoint

If either post-save writer fails, the item still exists, just without that asset.

Hardening for regulated workflows

When the form is legally required to have both the signature and the attachment, add a verification step:

Verify both assets exist after save

f365.events.onSave(async ({ itemId }) => {
  const item = await f365.sp.web.lists
    .getByTitle('Inspections')
    .items.getById(itemId)
    .select('CustomerSignature', 'Attachments')
    .get();

  if (!item.CustomerSignature || !item.Attachments) {
    // Flag it for follow-up.
    await f365.sp.web.lists
      .getByTitle('Inspections')
      .items.getById(itemId)
      .update({ NeedsReview: true });
    f365.ui.showToast(
      'Saved, but one or more attachments may have failed. Item flagged for review.',
      'warning'
    );
  }
});

Even better: run a daily background scan that finds NeedsReview === true items and notifies a moderator. That covers the silent-failure case where the user never sees the toast (page closed too quickly).

Submit-time validation

Block submit if the user hasn't provided what's required:

Block submit when signature is empty

f365.events.onBeforeSave(() => {
  if (!f365.field('CustomerSignature').value) {
    f365.ui.showAlert('A signature is required to submit this form.');
    f365.field('CustomerSignature').scrollIntoView();
    return { cancel: true };
  }
});