formtoDashboard

RSVP form

Give this to your agent

Add an RSVP form to my event page with formto: name, email, whether they are coming (yes, no or maybe), how many guests they bring and any dietary needs. Generate the HTML with formto, then restyle it to match the page.

Or paste the HTML

Replace YOUR_FORM_ID with your form’s public id (from npx -y https://formto.io/dl/cli-latest.tgz init or the dashboard), then restyle it. Keep the field names and the hidden _gotcha field.

<form id="formto-form" action="https://api.formto.io/f/YOUR_FORM_ID" method="post" enctype="application/x-www-form-urlencoded">
  <h2>RSVP</h2>
  <p>
    <label for="formto-name">Name</label>
    <input type="text" id="formto-name" name="name" required>
  </p>
  <p>
    <label for="formto-email">Email</label>
    <input type="email" id="formto-email" name="email" autocomplete="email" required>
  </p>
  <fieldset>
    <legend>Will you come?</legend>
      <label><input type="radio" name="attending" value="yes" required> Yes</label>
      <label><input type="radio" name="attending" value="no" required> No</label>
      <label><input type="radio" name="attending" value="maybe" required> Maybe</label>
  </fieldset>
  <p>
    <label for="formto-guests">Guests besides you</label>
    <input type="number" id="formto-guests" name="guests" min="0" max="10" step="1">
  </p>
  <p>
    <label for="formto-dietary">Dietary needs</label>
    <textarea id="formto-dietary" name="dietary" maxlength="1000" rows="5"></textarea>
  </p>
  <!-- Spam trap: people never see or fill this field. -->
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-10000px">
  <button type="submit">Send</button>
  <p data-formto-status role="status" aria-live="polite"></p>
</form>
<script>
  // Progressive enhancement: without JavaScript the form above posts natively.
  ;(function () {
    var form = document.getElementById('formto-form')
    if (!form || !window.fetch || !window.FormData) return
    form.addEventListener('submit', function (event) {
      event.preventDefault()
      var status = form.querySelector('[data-formto-status]')
      var button = form.querySelector('button[type=submit]')
      button.disabled = true
      fetch(form.action, { method: 'POST', body: new FormData(form), headers: { Accept: 'application/json' } })
        .then(function (res) {
          return res.json().then(function (body) {
            if (!res.ok || !body.success) throw new Error(body.error || 'Something went wrong. Please try again.')
            form.reset()
            status.textContent = 'Thanks, we got it.'
          })
        })
        .catch(function (err) {
          status.textContent = err.message || 'Could not send. Please try again.'
        })
        .finally(function () {
          button.disabled = false
        })
    })
  })()
</script>

The field definition

{
  "version": 2,
  "title": "RSVP",
  "fields": {
    "name": {
      "type": "string",
      "label": "Name",
      "required": true
    },
    "email": {
      "type": "email",
      "label": "Email",
      "required": true
    },
    "attending": {
      "type": "select",
      "label": "Will you come?",
      "required": true,
      "options": [
        {
          "value": "yes",
          "label": "Yes"
        },
        {
          "value": "no",
          "label": "No"
        },
        {
          "value": "maybe",
          "label": "Maybe"
        }
      ]
    },
    "guests": {
      "type": "number",
      "label": "Guests besides you",
      "integer": true,
      "min": 0,
      "max": 10
    },
    "dietary": {
      "type": "text",
      "label": "Dietary needs",
      "maxLength": 1000
    }
  },
  "fieldOrder": [
    "name",
    "email",
    "attending",
    "guests",
    "dietary"
  ],
  "submitter": {
    "emailField": "email",
    "nameField": "name"
  }
}