JavaScript Form Embed (Editor 2.0 only)

If you've read through the comparisons here and believe embedding a PandaDoc Form is best, let's get it done!

Embed Form Code Snippet

<div id='form-container-id'></div>

<script type="text/javascript">
    (function () {
        var config = {
            nodeId: 'form-container-id',
            width: '100%',
            height: '700px',
            url: 'embed-form-url',
            events: {
                loaded: function () {},
                started: function (data) {},
                completed: function (data) {},
                exception: function (data) {}
            },
            data: {
               recipients: {
                 ROLE_NAME: {
                   ROLE_TOKEN: 'ROLE_TOKEN_VALUE',
                   ...
                 }
               },
               metadata: {
                 KEY: 'VALUE',
                 ...
               },
               variables: {
                 VARIABLE_NAME: 'VARIABLE_VALUE',
                 ...
               },
               fields: {
                 FIELD_ID: 'FIELD VALUE',
               }
            }
        };
                
        const dataQueryString = config.data ? Object.keys(config.data)
      		.map(function (key) {
        		return '&' + key + '=' + encodeURIComponent(JSON.stringify(config.data[key]));
      		})
      		.join('') : '';

        var iframe = document.createElement('iframe');
        iframe.frameBorder = 0;
        iframe.src = config.url + dataQueryString;

        if (config.nodeId) {
            var node = document.getElementById(config.nodeId);
            node.style.height = config.height;
            node.style.width = config.width;
            iframe.height = '100%';
            iframe.width = '100%';
            node.append(iframe);
        } else {
            iframe.height = config.height;
            iframe.width = config.width;
            document.body.append(iframe);
        }

        var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
        var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message';

        window[eventMethod](messageEvent,function(e) {
          if (e && e.data && config && iframe && e.source === iframe.contentWindow) {

            try {
              var message = JSON.parse(e.data);
              if (message && message.event) {
                var event = message.event.replace('embed.form.', '');
                var callback = config.events ? config.events[event] : null;
                if (callback) {
                  callback(message.data);
                }
              }
            } catch(e) {}
          }
        },false);
    })();
</script>
<div id='form-container-id'></div>

<script type="text/javascript">
    (function () {
        var config = {
            nodeId: 'form-container-id',
            width: '100%',
            height: '700px',
            url: 'embed-form-url',
        };

        var iframe = document.createElement('iframe');
        iframe.frameBorder = 0;
        iframe.src = config.url;

        if (config.nodeId) {
            var node = document.getElementById(config.nodeId);
            node.style.height = config.height;
            node.style.width = config.width;
            iframe.height = '100%';
            iframe.width = '100%';
            node.append(iframe);
        } else {
            iframe.height = config.height;
            iframe.width = config.width;
            document.body.append(iframe);
        }

        var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
        var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message';

        window[eventMethod](messageEvent,function(e) {
          if (e && e.data && config && iframe && e.source === iframe.contentWindow) {

            try {
              var message = JSON.parse(e.data);
              if (message && message.event) {
                var event = message.event.replace('embed.form.', '');
                var callback = config.events ? config.events[event] : null;
                if (callback) {
                  callback(message.data);
                }
              }
            } catch(e) {}
          }
        },false);
    })();
</script>

Embed Form Config

* denotes a required parameter.

*Attribute: ExampleDescription
text * nodeIdid of the HTML element to which the form will be appended
text * widthThe width of an element JavaScript embed will be rendered
text * heightThe height of an element JavaScript embed will be rendered
text * URLURL of the form will be rendered
eventsIt is possible to capture events from an embedded form. You can subscribe to four types of events: loaded started completed exception
dataIt is possible to pre-fill recipients data, metadata and variables and fields

Pre-fill values using JavaScript config

It is possible to pre-fill recipients data, metadata, variables and fields

recipients - allows to pre-fill data in authorization form. All role tokens are supported

data: {
  recipients: {
    'Form Signer': {
      Email: '[email protected]',
      FirstName: 'John',
      LastName: 'Doe',
    }
  },
}

metadata - allows to set metadata for the document that will be generated from the form. Max limit - 10 key-value pairs

data: {
  metadata: {
    test_metadata_key: 'test value',
  }
}

variables - allows to set values to variables in the document. All variables(predefined and custom) are supported except Document.Value

data: {
  variables: {
    'Form signer.FirstName': 'John',
     custom_variable: 'custom variable value',
  }
}

fields - allows to set values to variables in the document. Text field, Checkbox, Date, Dropdown fields are supported

data: {
  fields: {
    TextField1: 'TextField1 value',
    Dropdown1: 'Dropdown selected value',
    Checkbox1: true,
    Date1: '2021-02-21T00:00:00.000Z'
  }
}

📘

Working with Date fields

Specify date formatting in PandaDoc template date field settings. Pass your date field value in the following ways:

fields: {  
    Date1: **'2021-02-21T00:00:00.000Z'**,  // ISO 8601 date and time  
    Date2: **'2021-02-21'**, // ISO 8601 date, will be added with UTC timezone  
    Date3: **'02/21/2021'** // date, will be added with UTC timezone  
}

Pre-fill values using direct web-link

It is possible to pre-fill recipients data, metadata, variables and fields without embedding form only adding needed data as url parameter:

&KEY=VALUE

where
KEY - metadata or recipients or variables
and
VALUE - encoded data that matches the js config

https://eform.pandadoc.com/?eform=test-eform-id&variables=%7B%22test%22%3A%22test%20value%22%7D

is similar to this code in config

data: {
 variables: {
   test_field_id: 'test value',
 }
},

Handling events

It is possible to capture events from an embedded form. You can subscribe to this events:

loaded - the form is loaded and a user is asked to enter contact details (recipients names and emails)

started - a user has entered contact details for all recipients, press button ‘review document’ for creating document from form

{
  recipients: [{
    first_name: ‘John’,
    last_name: ‘Doe’,
    email: ‘[email protected]’
  }],
}

completed - a user filled in the assigned fields and finalized the document

{
  document, //public document
}

exception - an error occurred while any recipient tries to finish their part

{
 uuid, //document uuid
}

Reload form after submission

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
<div id='form-container-17d74b52-853d-4299-bfa8-d3f89f1fd202'></div>
​
<script type="text/javascript">
    (function () {
        var config = {
            nodeId: 'form-container-17d74b52-853d-4299-bfa8-d3f89f1fd202',
            width: '100%',
            height: '700px',
            url: 'https://eform.pandadoc.com/?eform=ef41d1e6-f0f4-4d77-972e',
            events: {
                loaded: function () {},
                started: function (data) {},
                completed: function (data) {},
                exception: function (data) {}
            },
            data: {},
        };
​
        const dataQueryString = config.data ? Object.keys(config.data)
        .map(function (key) {
          return '&' + key + '=' + encodeURIComponent(JSON.stringify(config.data[key]));
        })
        .join('') : '';
​
        var iframe = document.createElement('iframe');
        iframe.frameBorder = 0;
        iframe.src = config.url + dataQueryString;
​
        if (config.nodeId) {
            var node = document.getElementById(config.nodeId);
            node.style.height = config.height;
            node.style.width = config.width;
            iframe.height = '100%';
            iframe.width = '100%';
            node.append(iframe);
        } else {
            iframe.height = config.height;
            iframe.width = config.width;
            document.body.append(iframe);
        }
​
        var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
        var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message';
​
        window[eventMethod](messageEvent,function(e) {
          if (e && e.data && config && iframe && e.source === iframe.contentWindow) {
            try {
              var message = JSON.parse(e.data);
              if (message && message.event) {
                if(message.event ===  "embed.form.completed"){
                    // If form is complete, reload the page after 1 second 
                    setTimeout(() => window.location.reload(), 1000)
                    return false
                };
                var event = message.event.replace('embed.form.', '');
                var callback = config.events ? config.events[event] : null;
                if (callback) {
                  callback(message.data);
                }
              }
            } catch(e) {
                console.log(e)
            }
          }
        },false);
    })();
</script>
</body>
</html>