Iterate over all form fields and widgets in the document

For the sake simplicity, we’ll show the general process on an example where we set a solid border for empty form fields:

function updateWidgetBorder(formField, widget) {
  if (formField.value) {
    // Reset the widget border properties when form field has a value.
    return widget
        .set('borderColor', undefined)
        .set('borderWidth', undefined)
        .set('borderStyle', undefined) 
  } else {
    // Set solid border if the form field does not have a value.
    return widget
      .set('borderColor', PSPDFKit.Color.LIGHT_RED)
      .set('borderWidth', 1)
      .set('borderStyle', 'solid')

async function refreshWidgets() {
  // Retrieve all form fields.
  const formFields = await instance.getFormFields()
  // Retrieve all widget annotations in the document.
  const widgetAnnotations = (await Promise.all(
    Array.from({ length: instance.totalPageCount }).map(async (_, pageIndex) =>
      (await instance.getAnnotations(pageIndex))
        .filter(it => it instanceof PSPDFKit.Annotations.WidgetAnnotation)
  )).flatMap(pageAnnotations => pageAnnotations.toArray())
  // Iterate over all form fields and their widgets to update their appearance.
  const widgetsToUpdate = formFields.flatMap(formField => {
    // Find all widget annotations for a given form field.
    const widgets = widgetAnnotations.filter(annotation => formField.annotationIds.contains(
    // Update all widgets based on the form field value.
    return => updateWidgetBorder(formField, widget))
  // Now perform the batch update with our updated widget annotations.
  return instance.update(widgetsToUpdate)

This has been tested with PSPDFKit for Web 2020.6.4

💡 Note: This example behaves similar to what can be achieved with required form fields. If you only need to style required fields then we recommend following this article