Checkboxes and multi-select
Receive every ticked checkbox and every selected option from an HTML form, as a list in JSON and webhooks and as a, b, c in email.
Checkbox groups and multi-select lists send several values under one name. SilentForms keeps every one of them, in the order the browser sent them, so a visitor who ticks three boxes shows up with three answers, not just the last one.
Checkbox groups#
Give every checkbox in the group the same name and a distinct value:
<form action="https://silentforms.com/api/submit" method="POST">
<input type="hidden" name="accessKey" value="YOUR_ACCESS_KEY_HERE">
<label for="email">Email</label>
<input id="email" type="email" name="email" required>
<fieldset>
<legend>What are you interested in?</legend>
<label><input type="checkbox" name="interests" value="Design"> Design</label>
<label><input type="checkbox" name="interests" value="Development"> Development</label>
<label><input type="checkbox" name="interests" value="Hosting"> Hosting</label>
</fieldset>
<input type="checkbox" name="botcheck" style="display: none;" tabindex="-1" autocomplete="off">
<button type="submit">Send</button>
</form>A <fieldset> with a <legend> tells screen readers that the boxes belong to one question.
Ticking Design and Hosting sends interests=Design&interests=Hosting, which arrives as the list ["Design", "Hosting"]. Unticked boxes are not sent at all, so a group with nothing ticked does not appear in the submission. Without a value attribute, a ticked box sends the word on, which is rarely what you want.
The name[] convention#
With repeated names, a field becomes a list only when more than one value arrives: ticking just Design gives the plain value "Design". If something downstream (a spreadsheet script, your own API) expects the same shape every time, end the name with []:
<label><input type="checkbox" name="interests[]" value="Design"> Design</label>
<label><input type="checkbox" name="interests[]" value="Development"> Development</label>
<label><input type="checkbox" name="interests[]" value="Hosting"> Hosting</label>A name ending in [] is always a list, even with one box ticked, and arrives without the brackets: the field is called interests. This is the convention PHP and Formspree use, so forms written for them keep working.
A single checkbox#
A lone checkbox, such as a newsletter opt-in, is one value:
<label>
<input type="checkbox" name="newsletter" value="yes">
Send me the monthly newsletter
</label>It arrives as newsletter: yes when ticked and is missing when not. If you need an explicit yes or no in every submission, use two radio buttons instead (see below).
Select multiple#
A <select multiple> behaves exactly like a checkbox group: each selected option is one value.
<label for="services">Services (hold Ctrl or Cmd to pick several)</label>
<select id="services" name="services[]" multiple size="4">
<option>Logo design</option>
<option>Website</option>
<option>Copywriting</option>
<option>Photography</option>
</select>Multi-select lists are awkward on desktop for people who do not know the Ctrl/Cmd trick. A checkbox group is usually easier to use.
Radio buttons#
Radio buttons share a name too, but the browser only ever sends the one that is selected, so they always arrive as a single value:
<fieldset>
<legend>Preferred contact method</legend>
<label><input type="radio" name="contact_method" value="Email" checked> Email</label>
<label><input type="radio" name="contact_method" value="Phone"> Phone</label>
</fieldset>Do not add [] to radio names: you would get a list with one item instead of a plain value.
Sending JSON from JavaScript#
Object.fromEntries(new FormData(form)) keeps only the last value of each name, so it silently drops all but one ticked box. Collect repeated names into arrays instead:
function formToObject(form) {
const data = {};
for (const [rawKey, value] of new FormData(form)) {
const isList = rawKey.endsWith('[]');
const key = isList ? rawKey.slice(0, -2) : rawKey;
if (key in data) {
data[key] = [].concat(data[key], value);
} else {
data[key] = isList ? [value] : value;
}
}
return data;
}
const data = formToObject(form);
// { email: "[email protected]", interests: ["Design", "Hosting"], ... }A JSON body can also send arrays directly, for example { "interests": ["Design", "Hosting"] }. Up to 100 values per field are kept.
How the values look#
| Where | interests with Design and Hosting ticked |
|---|---|
| Notification email | Design, Hosting |
| Webhook payload | "interests": ["Design", "Hosting"] |
| Dashboard submissions | Design, Hosting |
| CSV export | One cell: Design, Hosting |
Webhooks get a real JSON array, so automation tools can loop over the values or join them however they like. See Webhooks.
Next steps#
- Form with every option: checkbox groups alongside every other field.
- AJAX form with JavaScript: a complete
fetchexample. - Google Sheets: write list values into a spreadsheet.