Articles in this section
Category / Section

Signature Field Validation in React PDF Viewer (Enable/Disable Handwritten signature on basis of Current User)

9 mins read

Signature Field Validation in React PDF Viewer (Enable/Disable Handwritten signature on basis of Current User)

Description

This article provides a solution for managing handwritten signature fields in React PDF Viewer. The configuration allows you to enable or disable signature capabilities based on the current user, offering tailored access and reinforcing document security.

Solution

To enable or disable handwritten signatures in the React PDF Viewer based on user roles, set up user-specific permissions and dynamically update form field properties. Initialize user details with associated colors and permissions. When the application loads, set the current user and adjust form field access using the updateUserFormField function, which alters the isReadOnly status based on the selected user. Utilize a dropdown to switch users, ensuring that form fields are only editable by the appropriate role. This method ensures secure and role-specific interaction with signature fields in the PDF Viewer.

Prerequisites
  1. Syncfusion PDF Viewer Setup: Make sure the Syncfusion PDF Viewer is installed and set up in your React project. Follow the Getting Started with Syncfusion PDFViewer for React guide if you haven’t already.
  2. Basic Knowledge of React: Familiarity with React components and the basic setup of React projects will help you follow along with the implementation.
Implementation Steps
Set Up User Details and Components

Set up initial user details and the PDFViewer component interface.

import * as ReactDOM from 'react-dom/client';
import * as React from 'react';
import './index.css';
import {
  PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView,
  ThumbnailView, Print, TextSelection, Annotation, TextSearch, FormFields, FormDesigner, Inject
} from '@syncfusion/ej2-react-pdfviewer';
export function App() {
  var currentUser = "";
  var currentUserColor = "#ff0000";
  var userDetails = [];
  var colorPicker;
  var submitButton;
  var pdfViewer;

  window.onload = function () {
    //create user collections
    userDetails.push(new UserDetails("manager@mycompany.com", "#ff0000", []));
    userDetails.push(new UserDetails("engineer@mycompany.com", "#00ff00", []));
    //retrieve the ej2 control instance
    colorPicker = document.getElementById("colorpicker");
    submitButton = document.getElementById("finishSigningBtn");
    pdfViewer = document.getElementById('pdfviewer').ej2_instances[0];
    submitButton.addEventListener('click', downloadDocument);
    //bind the function to dropdown change
    setCurrentUser('manager@mycompany.com');
    var viewerContainer = document.getElementById("pdfviewer_viewerContainer");
    //checked the form designer toolbar is expand or collapse and update the form fields based on the user type.
    const observer = new MutationObserver(function (mutationsList, observer) {
      for (let mutation of mutationsList) {
        if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
          // Handle the resize event here
          updateUserFormField();
        }
      }
    });
    observer.observe(viewerContainer, { attributes: true });
  }
User Interaction and Field Management

Manage user selection and dynamically adjust form fields for the current user:

function dropdownChange(e) {
    currentUser = e.target.value;
    updateUserFormField();
  }

  function updateUserFormField() {
    var user = userDetails.filter(userDetail => userDetail.userName === currentUser);
    currentUserColor = colorPicker.value = user[0].userColor;
    //hide the field based on the user type
    var otherUserDetails = userDetails.filter(userDetail => userDetail.userName !== currentUser)[0];
    for (var i = 0; i < otherUserDetails.fieldIds.length; i++) {
      var otherUserField = document.getElementById(otherUserDetails.fieldIds[i].id + "_content_html_element");
      if (!pdfViewer.designerMode) {
        if (otherUserField) {
          pdfViewer.formDesigner.updateFormField(otherUserDetails.fieldIds[i].id, { isReadOnly: true });
          var currentFormField = pdfViewer.formFieldCollections.filter(formField => formField.id === otherUserDetails.fieldIds[parseInt(i.toString(), 10)].id)[0];
          if (!currentFormField.value && otherUserField)
            otherUserField.style.display = 'none';
        }
      } else {
        if (otherUserField) {
          //Show the form fields in designer mode
          pdfViewer.formDesigner.updateFormField(otherUserDetails.fieldIds[i].id, { isReadOnly: false });
          document.getElementById(otherUserDetails.fieldIds[i].id + "_content_html_element").style.display = 'block';
        }
      }
    }
    //show the field based on the user type.
    var currentUserDetails = userDetails.filter(userDetail => userDetail.userName === currentUser)[0];
    for (var j = 0; j < currentUserDetails.fieldIds.length; j++) {
      var currentUserField = document.getElementById(currentUserDetails.fieldIds[j].id + "_content_html_element");
      if (currentUserField) {
        pdfViewer.formDesigner.updateFormField(currentUserDetails.fieldIds[j].id, { isReadOnly: false });
        document.getElementById(currentUserDetails.fieldIds[j].id + "_content_html_element").style.display = 'block';
      }
    }
  }
Form Validation and Submission

Use validation checks to control the state of the submit button:

// validate the form fields
  function fieldChange(arg) {

    var viewer = pdfViewer;
    var errorMessage = "Required Field(s): ";
    var forms = viewer.formFieldCollections;
    var flag = false;
    var isAllFieldFilled = true;
    var radioGroupName = "";
    for (var i = 0; i < forms.length; i++) {
      var text = "";
      if (forms[i].type.toString() === "Checkbox" && forms[i].isChecked === false) {
        text = forms[i].name;
        isAllFieldFilled = false;
      }
      else if (forms[i].type === "RadioButton" && flag === false) {
        radioGroupName = forms[i].name;
        if (forms[i].isSelected === true)
          flag = true;
      }
      else if (forms[i].type.toString() !== "Checkbox" && forms[i].type !== "RadioButton" && (forms[i].value === "" || ((typeof arg.newValue === 'string') && arg.newValue === ""))) {
        text = forms[i].name;
        isAllFieldFilled = false;
      }
      if (text !== "") {
        if (errorMessage === "Required Field(s): ") {
          errorMessage += text;
        }
        else {
          errorMessage += ", " + text;
        }
      }

    }
    if (!flag && radioGroupName !== "") {
      if (errorMessage === "Required Field(s): ")
        errorMessage += radioGroupName;
      else
        errorMessage += ", " + radioGroupName;
      isAllFieldFilled = false;
    }
    if (isAllFieldFilled) {
      submitButton.disabled = false;
    } else {
      submitButton.disabled = true;
    }

  }

  function addFormField(arg) {
    var col = currentUserColor === '#ff0000' ? 'red' : 'green';
    pdfViewer.formDesigner.updateFormField(arg.field.id, { backgroundColor: col });
    var currentUserDetails = userDetails.filter(userDetail => userDetail.userName === currentUser)[0];
    var currentFormField = pdfViewer.formFieldCollections.filter(formField => formField.id === arg.field.id)[0];
    currentUserDetails.fieldIds.push(currentFormField);
  }

  function downloadDocument(args) {
    pdfViewer.download();
  }

  function setCurrentUser(username) {
    if (userDetails.findIndex(userDetail => userDetail.userName === username) !== -1) {
      currentUser = username;
      document.getElementById('ddlelement').value = currentUser;
      updateUserFormField();
    }
  }

  class UserDetails {
    constructor(userName, userColor, fieldIds) {
      this.userName = userName;
      this.userColor = userColor;
      this.fieldIds = fieldIds;
    }
  }
Ensuring Integration within Your Component

Make sure these functions are tightly integrated with the rest of your component, ensuring that they interact with the PDF Viewer and DOM elements correctly.

  return (
    <div>
      <div className="control-container">
        <div className="userContainerRow">
          <div className="column userContainer">
            <div className="user-label-container">
              <div className="user-label">
                Choose the user:
              </div>
              <select id="ddlelement" onChange={dropdownChange}>
                <option value="manager@mycompany.com">manager@mycompany.com</option>
                <option value="engineer@mycompany.com">engineer@mycompany.com</option>
              </select>
            </div>
            <div className="color-label-container">
              <div className="color-label">
                Color:
              </div>
              <input type="color" id="colorpicker" value="#ff0000" disabled={true}></input>
            </div>
          </div>
          <div className="column finishSignBtn">
            <button id="finishSigningBtn" disabled >Finish Signing</button>
          </div>
        </div>
      </div>
      <div className='control-section'>
        <div className="column viewerContainer">
          <PdfViewerComponent
            id="pdfviewer"
            documentPath='fill_and_sign_empty.pdf'
            serviceUrl="https://localhost:44309/pdfviewer"
            enableFormFieldsValidation={true}
            showNotificationDialog={false}
            formFieldAdd={addFormField}
            formFieldPropertiesChange={fieldChange}
            toolbarSettings={{ showTooltip: false, toolbarItems: ["OpenOption", "PageNavigationTool", "MagnificationTool", "FormDesignerEditTool", "PrintOption", "DownloadOption"] }}
            height='640px'>
            {/* Inject the required services */}
            <Inject services={[Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, BookmarkView, ThumbnailView,
              Print, TextSelection, TextSearch, FormFields, FormDesigner]} />
          </PdfViewerComponent>
        </div>
      </div>
    </div>
  );
Key Features Used in the Code
  1. Form Field Management: Controls field enablement and visibility using updateFormField.
  2. Form Field Validation: Ensures form completion for signature submission.
Sample Link:

You can access the complete sample via our GitHub Sample Repository

Steps to run the sample:
  1. Run the Web Service Sample: Start the web service sample provided and take note of the URL it is hosted on.
  2. Configure the Client: In the React project, set the server URL obtained in the appropriate configuration field.
  3. Start the Client Application: Launch the React application
Conclusion:

I hope you found this article helpful in learning how to enable or disable handwritten signatures in React PDF Viewer based on user roles. This method can be used to manage access dynamically and enhance document security by customizing signature capabilities for each user.

You can refer to React PDF feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. You can also explore our React PDF Viewer example to understand how to create and manipulate data.
For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.

If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied