> Lettrove docs 1.x · https://docs.lettrove.com/docs/editor/forms

# Forms

Landing pages and popups have a **form** block: labelled fields, a submit button, and a thank-you
message. Emails do not (most inboxes will not run a form).

Lettrove never receives what people type into a form. Each submission goes to **you**, one of two
ways, chosen in the form's settings in the editor under **When the form is sent**:

| Where it goes | Choose | You write |
|---|---|---|
| **Your page's code** (the default) | **Your site’s code** | A listener for the `lettrove:form` event |
| **Your own URL** | **Post to a URL**, and give the address in **Post to** | A route that accepts a normal HTML form post |

## The fields

Each field has a label, a name, and a type: `text`, `email`, `tel`, `number`, `textarea`,
`select` (with its options) or `checkbox`. A field can be required. The browser checks required
fields and email addresses before anything is sent.

The **name** is the key you receive. It follows the label until you change it by hand: a field
labelled "Work email" is named `work_email` (lower case, words joined by `_`). Names are letters,
digits, `-` and `_`.

## Way 1: in your page's code

When someone submits, the page you published fires a `lettrove:form` event on `document`, and the
form is replaced by its thank-you message. Listen for it wherever you publish the page or popup:

```html
<script>
  document.addEventListener('lettrove:form', async (event) => {
    const { designId, formId, values } = event.detail;
    // designId: the design the form is in — the same id your editor and server use
    // formId:   which form, when a design has more than one
    // values:   { email: 'ada@example.com', company: 'Acme', newsletter: 'yes' }

    await fetch('/api/signups', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(values),
    });
  });
</script>
```

Every value is a string. A checkbox is `'yes'` when ticked and `'no'` when not.

## Way 2: posted to your URL

The form posts to the address you give, as an ordinary HTML form does
(`application/x-www-form-urlencoded`), and the browser follows your response. So your route should
answer with a page, or redirect to one:

```js
// Express
app.post('/signup', express.urlencoded({ extended: false }), async (req, res) => {
  await saveSignup(req.body); // { email: 'ada@example.com', company: 'Acme', newsletter: 'yes' }
  res.redirect(303, '/thanks');
});
```

A ticked checkbox posts `yes`; an unticked one posts nothing, as every HTML form does.

## Good to know

- In the editor the form is drawn but never submits, so your users can lay it out freely.
- Treat submitted values like any other input from the internet: validate them on your server.
