Require form controls to have a unique name

Rule ID:
form-dup-name
Category:
HTML Syntax and concepts
Standards:
-

While not strictly required by the HTML standard using the same name on multiple form controls can be confusing to read and is often an oversight by the developer. Submitting form with duplicate names are converted to arrays and some javascript frameworks assume the name is unique when serializing form data.

The form control name also plays a role in the autocomplete heurestics so using good names is important to get accurate results.

By default, radiobuttons (<input type="radio">) is generally ignored by this rule as they are typically using the same name on purpose but they cannot share the same name as other controls.

Each <form> and <template> element tracks the names separately, i.e. you can have two forms with colliding names.

Rule details

Examples of incorrect code for this rule:

<form>
    <input name="foo">
    <input name="foo">
</form>
error: Duplicate form control name "foo" (form-dup-name) at inline:3:18:
  1 | <form>
  2 |     <input name="foo">
> 3 |     <input name="foo">
    |                  ^^^
  4 | </form>


1 error found.

Examples of correct code for this rule:

<form>
    <input name="foo">
    <input name="bar">
</form>

Radiobuttons

By default, radiobuttons may share the same name:

<form>
    <input name="foo" type="radio">
    <input name="foo" type="radio">
</form>

They cannot share the same name as other controls:

<form>
    <input name="foo" type="text">
    <input name="foo" type="radio">
</form>
error: Duplicate form control name "foo" (form-dup-name) at inline:3:18:
  1 | <form>
  2 |     <input name="foo" type="text">
> 3 |     <input name="foo" type="radio">
    |                  ^^^
  4 | </form>


1 error found.

See the shared option to add this behaviour for other controls.

Options

This rule takes an optional object:

{
  "allowArrayBrackets": true,
  "allowCheckboxDefault": true,
  "shared": ["radio"]
}

allowArrayBrackets

Form control names ending with [] is typically used to signify arrays. With this option names ending with [] may be shared between controls.

With this option disabled the following is incorrect:

<form>
    <input name="foo[]">
    <input name="foo[]">
</form>
error: Duplicate form control name "foo[]" (form-dup-name) at inline:3:18:
  1 | <form>
  2 |     <input name="foo[]">
> 3 |     <input name="foo[]">
    |                  ^^^^^
  4 | </form>


1 error found.

With this option enabled the following is correct:

<form>
    <input name="foo[]">
    <input name="foo[]">
</form>

allowCheckboxDefault

When serializing form data (e.g. using FormData or form submission) unchecked checkboxes are omitted from the entry list. A common pattern with server-side frameworks is to include an <input type="hidden" value="0"> or similar as a default value, i.e. if the checkbox is unchecked the default value is used.

With this option disabled the following is incorrect:

<form>
    <input name="foo" value="0" type="hidden">
    <input name="foo" value="1" type="checkbox">
</form>
error: Duplicate form control name "foo" (form-dup-name) at inline:3:18:
  1 | <form>
  2 |     <input name="foo" value="0" type="hidden">
> 3 |     <input name="foo" value="1" type="checkbox">
    |                  ^^^
  4 | </form>


1 error found.

With this option enabled the following is correct:

<form>
    <input name="foo" value="0" type="hidden">
    <input name="foo" value="1" type="checkbox">
</form>

Note that even with this option enabled at most one checkbox may share the same name as a single hidden control. Use two or more hidden or two or more checkboxes with the same name is still an error.

shared

By default only <input type="radio"> can have a shared common name. This options lets you specify additional controls that may have a shared common name.

With this option set to ["radio"] the following is incorrect:

<form>
    <input name="foo" type="checkbox">
    <input name="foo" type="checkbox">
</form>
error: Duplicate form control name "foo" (form-dup-name) at inline:3:18:
  1 | <form>
  2 |     <input name="foo" type="checkbox">
> 3 |     <input name="foo" type="checkbox">
    |                  ^^^
  4 | </form>


1 error found.

With this option set to ["radio", "checkbox"] the following is correct:

<form>
    <input name="foo" type="checkbox">
    <input name="foo" type="checkbox">
</form>

The name cannot be shared between different types of controls:

<form>
    <input name="foo" type="checkbox">
    <input name="foo" type="radio">
</form>
error: Duplicate form control name "foo" (form-dup-name) at inline:3:18:
  1 | <form>
  2 |     <input name="foo" type="checkbox">
> 3 |     <input name="foo" type="radio">
    |                  ^^^
  4 | </form>


1 error found.

Metadata

This rule check all elements marked as formAssociated with the listed property.

To use with custom elements set the listed property to true:

import { defineMetadata } from "html-validate";

export default defineMetadata({
  "custom-element": {
    formAssociated: {
      listed: true,
    },
  },
});

Version history