The form-field element

Overview

The <form-field> element is a wrapper element that provides a label element and common layouts for form elements like <input>, <select>, and <textarea> elements.

The goal of the element is to allow hand-written <form>s to be possible with fewer elements when doing the most common form designs.

Basic Examples

The <form-field> element is used as a helper to whittle down the boilerplate necessary to have well-functioning and well-formatted form field.

The element may include a <label> element or several <label> elements, depending on whether the input is a collection of inputs or not.

If the content is only a single child, that child will be rendered in a <label> element with a span to hold the text of the field's title. The content of that span will be populated by any value provided as the label attribute on the <form-field> element.

If the content is multiple inputs, the inputs will be rendered in a <div class="container"> element with a span to hold the text of the field's title, which should describe the whole group. The content of that span will be populated by any value provided as the label attribute on the <form-field> element.

Each of the provided inputs will be rendered in their own <label> elements, each including titles for the inputs based on the input values.

In the examples below, note the difference in HTML written with the the <form-field> element vs with non-custom HTML elements. For only 4 fields, the difference is still apparent. But as forms grow, the benefit of using the <form-field> element grows too.

<form-field> Element
<form-field label="No Input" placeholder="This form-field has no inputs"></form-field> <form-field label="Custom Text Input"> <input type="text" name="username" placeholder="This input is defined in the html" /> </form-field> <form-field label="Password"> <input type="password" name="password" /> </form-field> <form-field label="Ways for Love to Grow"> <select name="love-growth-method"> <option value="good">Good</option> <option value="bad">Bad</option> <option value="mediocre">Mediocre</option> </select> </form-field> <form-field label="Subs"> <input type="checkbox" name="subs" value="meatball" /> <input type="checkbox" name="subs" value="turkey-bacon-club" /> <input type="checkbox" name="subs" value="philly-cheesesteak" /> <input type="checkbox" name="subs" value="chicken-salad" /> </form-field>
Plain HTML
<label class="container"> <span class="field-label">No Input</span> <input placeholder="This form-field has no inputs"> </label> <label class="container"> <span class="field-label">Custom Text Input</span> <input type="text" name="username" placeholder="This input is defined in the html"> </label> <label class="container"> <span class="field-label">Password</span> <input type="password" name="password"> </label> <label class="container"> <span class="field-label">Ways for Love to Grow</span> <select name="love-growth-method"> <option value="good">Good</option> <option value="bad">Bad</option> <option value="mediocre">Mediocre</option> </select> </label> <div class="container"> <span class="field-label">Subs</span> <label class="option"> <input type="checkbox" name="subs" value="meatball"> <span class="label">Meatball</span> </label> <label class="option"> <input type="checkbox" name="subs" value="turkey-bacon-club"> <span class="label">Turkey Bacon Club</span> </label> <label class="option"> <input type="checkbox" name="subs" value="philly-cheesesteak"> <span class="label">Philly Cheesesteak</span> </label> <label class="option"> <input type="checkbox" name="subs" value="chicken-salad"> <span class="label">Chicken Salad</span> </label> </div>

Helpers

The <form-field> element provides "slots" for helper elements that a field may need. Since the <form-field> element does not use the shadowDOM, it doesn't use acutal <slot> functionality for this feature. Instead, parts of a template are replaced dynamically with whatever content sets its slot attribute to either prefix or postfix.

These slots are useful for things like requirement indicators, pre-defined values, or complex styling.

Content Without a slot attribute

All elements that are not an expected input, or assigned a slot attribute will be appended to the end of the form-field's container.

This kind of content is useful for error messages, or additional notes about the specific field.

Note how the the "Before" element is appended after the <input> element.

<form-field label="Username"> <div>Before</div> <input type="text" name="username" placeholder="Same as it ever was" /> <div>After</div> </form-field>
Before
After

prefix slot

Setting a child element's slot attribute to a value of prefix will place that element directly after the input.

In the case of input groups, the prefix element will be duplicated before each input.

<form-field label="Text"> <input type="text" name="prefix-text" placeholder="Prefix" /> <span slot="prefix">Before</span> </form-field> <form-field label="Group"> <input type="checkbox" name="prefix-booleans" value="0" /> <input type="checkbox" name="prefix-booleans" value="1" /> <input type="checkbox" name="prefix-booleans" value="2" /> <input type="checkbox" name="prefix-booleans" value="3" /> <span slot="prefix">Before</span> </form-field>
Before Before

postfix slot

Giving a child element the attribute value of postfix will place that element after the input.

In the case of input groups, the postfix element will be duplicated after each input.

<form-field label="Text"> <span slot="postfix">After</span> <input type="text" name="postfix-text" placeholder="Postfix" /> </form-field> <form-field label="Group"> <span slot="postfix">After</span> <input type="checkbox" name="postfix-booleans" value="0" /> <input type="checkbox" name="postfix-booleans" value="1" /> <input type="checkbox" name="postfix-booleans" value="2" /> <input type="checkbox" name="postfix-booleans" value="3" /> </form-field>
After After

Practical Example

This example implements a simple search control using the slots and additional content.

<form-field label="Search" class="search" input-selector="input[type='search']"> <input type="search" name="query" /> <select slot="prefix" class="type"> <option value="name">Name</option> <option value="tag">Tag</option> <option value="id">Product ID</option> </select> <button slot="postfix">&#x1f50d;</button> <div class="error">This is where error text would be displayed.</div> </form-field>
This is where error text would be displayed.

Form Data

The <form-field> element does not interfere with FormData when a form is submitted, so any named inputs can have their content collected in a FormData object, like normal.

In this example, the <form>'s submit event is being handled by having each of its fields are rendered to a dialog:

First String
The Calvary
Texty Bois
Special Case
Custom Features Before After
Web Coast Customs <file-input> Custom Element (repo) <image-input> Custom Element (repo)
Weird Inputs
Deprecated