← All recipes

Consent form

Build a consent form the recipient fills in by choosing. You learn dropdown, list, radio and button fields, and the required and read-only flags.

Use this template

What this teaches

  • field-select
  • field-list
  • field-radio
  • field-button
  • field-readonly
  • style-bg
  • style-radius
  • style-border
  • node-rect

Building it in the editor

  1. Add a field and set its kind to dropdown. When the options box appears, put one option per line — we do not split on commas because a value may contain one.
  2. With no options the field is skipped and reported in warnings — a box with nothing to choose looks broken to the person filling it in.
  3. Use the list kind to let several be chosen. Use radio when only one may be chosen but all should stay visible.
  4. A radio group divides the box you drew into as many rows as there are options. With three options, draw the box tall enough for three.
  5. A button field creates something the viewer can press. We attach no behaviour to it — attaching a script would create an arbitrary code surface.
  6. Turn on read-only to show a value that must not be edited. This too is only a flag; whether it is enforced is up to the program that opens the PDF.
  7. Put the fields inside a rectangle with a background and a corner radius so they read as one group. Give the rectangle a border and the grouping survives printing too.

Building it with the schema and API

  1. select, list and radio take a string array in props.options. When it is empty that one field is skipped.
  2. required and readonly are booleans. Leave them false on other types — the union schema requires the key on every node.
  3. Options can contain non-Latin text. The PDF viewer draws them with its own font — if we drew them, the standard font could not encode those characters.
  4. Up to 500 fields per document. Beyond that we cut and tell you.

The finished document

The JSON below is exactly the document those two routes produce. Our tests validate it and check that it renders without warnings, so you can paste it and use it as is.

EXAMPLE
{
  "v": 1,
  "unit": "px",
  "page": {
    "size": "a4",
    "orientation": "portrait",
    "margin": {
      "t": 48,
      "r": 48,
      "b": 56,
      "l": 48
    },
    "header": "",
    "footer": ""
  },
  "fonts": [],
  "styles": [
    {
      "id": "s_h1",
      "fontFamily": "Liberation Sans",
      "fontSize": 22,
      "fontWeight": 700,
      "italic": false,
      "color": "#111111",
      "bg": "transparent",
      "align": "left",
      "valign": "top",
      "lineHeight": 1.5,
      "border": "none",
      "radius": 0,
      "opacity": 1
    },
    {
      "id": "s_l",
      "fontFamily": "Liberation Sans",
      "fontSize": 12,
      "fontWeight": 400,
      "italic": false,
      "color": "#333333",
      "bg": "transparent",
      "align": "left",
      "valign": "top",
      "lineHeight": 1.5,
      "border": "none",
      "radius": 0,
      "opacity": 1
    },
    {
      "id": "s_box",
      "fontFamily": "Liberation Sans",
      "fontSize": 12,
      "fontWeight": 400,
      "italic": false,
      "color": "#111111",
      "bg": "#f7f8fa",
      "align": "left",
      "valign": "top",
      "lineHeight": 1.5,
      "border": "1px solid #dfe3e8",
      "radius": 12,
      "opacity": 1
    },
    {
      "id": "s_f",
      "fontFamily": "Liberation Sans",
      "fontSize": 12,
      "fontWeight": 400,
      "italic": false,
      "color": "#111111",
      "bg": "transparent",
      "align": "left",
      "valign": "top",
      "lineHeight": 1.5,
      "border": "none",
      "radius": 0,
      "opacity": 1
    }
  ],
  "nodes": [
    {
      "id": "n_title",
      "parent": "",
      "order": 0,
      "type": "label",
      "x": 0,
      "y": 0,
      "w": 697,
      "h": 30,
      "show": "",
      "styleId": "s_h1",
      "props": {
        "text": "Personal data consent form",
        "src": "",
        "fit": "",
        "thickness": 0,
        "stroke": "",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Title"
    },
    {
      "id": "n_box",
      "parent": "",
      "order": 1,
      "type": "rect",
      "x": 0,
      "y": 52,
      "w": 697,
      "h": 330,
      "show": "",
      "styleId": "s_box",
      "props": {
        "text": "",
        "src": "",
        "fit": "",
        "thickness": 1,
        "stroke": "#dfe3e8",
        "fill": "#f7f8fa",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Field group"
    },
    {
      "id": "n_p1",
      "parent": "n_box",
      "order": 2,
      "type": "label",
      "x": 20,
      "y": 20,
      "w": 300,
      "h": 18,
      "show": "",
      "styleId": "s_l",
      "props": {
        "text": "Department",
        "src": "",
        "fit": "",
        "thickness": 0,
        "stroke": "",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Department caption"
    },
    {
      "id": "n_dept",
      "parent": "n_box",
      "order": 3,
      "type": "field",
      "x": 20,
      "y": 42,
      "w": 300,
      "h": 28,
      "show": "",
      "styleId": "s_f",
      "props": {
        "text": "",
        "src": "",
        "fit": "",
        "thickness": 1,
        "stroke": "#8a93a0",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "select",
        "fieldName": "dept",
        "options": [
          "Sales",
          "Engineering",
          "Operations"
        ],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Department select"
    },
    {
      "id": "n_p2",
      "parent": "n_box",
      "order": 4,
      "type": "label",
      "x": 360,
      "y": 20,
      "w": 300,
      "h": 18,
      "show": "",
      "styleId": "s_l",
      "props": {
        "text": "Data collected (choose several)",
        "src": "",
        "fit": "",
        "thickness": 0,
        "stroke": "",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Items caption"
    },
    {
      "id": "n_items",
      "parent": "n_box",
      "order": 5,
      "type": "field",
      "x": 360,
      "y": 42,
      "w": 300,
      "h": 80,
      "show": "",
      "styleId": "s_f",
      "props": {
        "text": "",
        "src": "",
        "fit": "",
        "thickness": 1,
        "stroke": "#8a93a0",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "list",
        "fieldName": "collected",
        "options": [
          "Name",
          "Phone",
          "Email",
          "Address"
        ],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Items list"
    },
    {
      "id": "n_p3",
      "parent": "n_box",
      "order": 6,
      "type": "label",
      "x": 20,
      "y": 96,
      "w": 300,
      "h": 18,
      "show": "",
      "styleId": "s_l",
      "props": {
        "text": "Retention period",
        "src": "",
        "fit": "",
        "thickness": 0,
        "stroke": "",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Retention caption"
    },
    {
      "id": "n_keep",
      "parent": "n_box",
      "order": 7,
      "type": "field",
      "x": 20,
      "y": 118,
      "w": 300,
      "h": 84,
      "show": "",
      "styleId": "s_f",
      "props": {
        "text": "",
        "src": "",
        "fit": "",
        "thickness": 1,
        "stroke": "#8a93a0",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "radio",
        "fieldName": "retention",
        "options": [
          "1 year",
          "3 years",
          "Until consent is withdrawn"
        ],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Retention choice"
    },
    {
      "id": "n_p4",
      "parent": "n_box",
      "order": 8,
      "type": "label",
      "x": 20,
      "y": 216,
      "w": 640,
      "h": 18,
      "show": "",
      "styleId": "s_l",
      "props": {
        "text": "Date issued (read-only)",
        "src": "",
        "fit": "",
        "thickness": 0,
        "stroke": "",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Date caption"
    },
    {
      "id": "n_when",
      "parent": "n_box",
      "order": 9,
      "type": "field",
      "x": 20,
      "y": 238,
      "w": 300,
      "h": 28,
      "show": "",
      "styleId": "s_f",
      "props": {
        "text": "",
        "src": "",
        "fit": "",
        "thickness": 1,
        "stroke": "#8a93a0",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "text",
        "fieldName": "issued_at",
        "options": [],
        "required": false,
        "readonly": true,
        "html": ""
      },
      "name": "Date issued"
    },
    {
      "id": "n_submit",
      "parent": "n_box",
      "order": 10,
      "type": "field",
      "x": 360,
      "y": 238,
      "w": 160,
      "h": 32,
      "show": "",
      "styleId": "s_f",
      "props": {
        "text": "",
        "src": "",
        "fit": "",
        "thickness": 1,
        "stroke": "#111111",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "button",
        "fieldName": "submit",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Submit button"
    },
    {
      "id": "n_submit_l",
      "parent": "n_box",
      "order": 11,
      "type": "label",
      "x": 360,
      "y": 274,
      "w": 300,
      "h": 16,
      "show": "",
      "styleId": "s_l",
      "props": {
        "text": "We create somewhere to press — no behaviour is attached.",
        "src": "",
        "fit": "",
        "thickness": 0,
        "stroke": "",
        "fill": "",
        "repeat": "",
        "as": "",
        "break": "",
        "keep": "",
        "padding": 0,
        "padY": 0,
        "padX": 0,
        "align": "",
        "valign": "",
        "wrap": "",
        "bind": "",
        "headerHeight": 0,
        "rowHeight": 0,
        "max": 0,
        "columns": [],
        "rows": 0,
        "cells": [],
        "chartKind": "",
        "codeKind": "",
        "ecc": "",
        "fieldKind": "",
        "fieldName": "",
        "options": [],
        "required": false,
        "readonly": false,
        "html": ""
      },
      "name": "Button caption"
    }
  ]
}

The request body. Put the document above into template and the data below into data.

REQUEST
{
  "template": "(the document above)",
  "data": {}
}