Skip to content
Components, switch product

Native forms

Every element that holds a value is a form control, like <input> or <select>. Give it a name inside a <form> and it submits, validates and resets with the form, with no JavaScript of your own.

Code of the example above
TextInputNativeForm.tsx
import { useState, type SubmitEvent } from 'react';
import { GuiButton, GuiTextinput } from '@golemui/gui-components/react';
import '@golemui/gui-components/index.css';
export function TextInputNativeForm() {
const [result, setResult] = useState('');
const onSubmit = (event: SubmitEvent<HTMLFormElement>) => {
event.preventDefault();
const data = Object.fromEntries(new FormData(event.currentTarget));
setResult(`Submitted ${JSON.stringify(data)}`);
};
return (
<form id="newsletter" onSubmit={onSubmit}>
<div className="gui-grid gui-grid--row">
<div className="gui-grid__cell gui-grid__cell--span-3">
<GuiTextinput label="Email" name="email" required />
</div>
<div className="gui-grid__cell">
<GuiButton type="submit" label="Subscribe" />
</div>
</div>
<p id="newsletter-result" role="status">
{result}
</p>
</form>
);
}

An element takes part in its form only when it has a name. Without one it stays out: it submits nothing and never blocks a submit. That keeps an element that only displays a value, or one inside a composite element, out of the form.

The element belongs to the <form> around it. Read it back from the element’s form property.

The form submits the value under the element’s name, and FormData reads it like any other field:

ValueSubmitted as
Text or a numberThe text, such as ada@example.com or 3.
true, such as a checked checkboxon, like a native checkbox.
A list, such as the values of a tags fieldOne entry per item, all under the same name.
An object, such as a date rangeJSON.
Empty: no value, an empty string or list, falseNothing.

Each component page says what that element submits, in its “In a form” section.

An element with a name validates like a native control:

  • required blocks a submit while the element is empty;
  • bounds, such as minimum and maximum on a number or min-date and max-date on a date or a range of dates, block a value outside them;
  • a disabled date or time range blocks a value inside it.

They check the value however it got there, typed by the user or set from your code.

The browser stops the submit, focuses the control and shows its message, pointing at the part of the element that holds the value. The messages are in English by default; translate them like the other built-in strings, under keys such as valueMissing, rangeUnderflow and minDate. See i18n.

The element has the validation API of a native control:

MemberWhat it does
checkValidity()Returns whether the value is valid, without showing anything.
reportValidity()The same, and shows the browser’s message when it isn’t.
validityThe ValidityState, such as validity.valueMissing.
validationMessageThe message the browser would show.
formThe <form> the element belongs to.

The errors attribute shows messages from your own validation, under the field, and marks it as invalid for assistive technology. It doesn’t block the submit: check the values in your submit handler, or set the errors from a gui-change listener as the user works.

touched holds the errors back: while it is false, the field doesn’t show them. Leave it unset, unless you validate before the user has touched the field and set it to true once they have.

  • form.reset() restores the value each element started with.
  • A disabled element, by its disabled attribute or property or a disabled <fieldset> around it, can’t be changed, isn’t validated, and the form doesn’t submit it. Setting the property sets the attribute, as on a native control.
  • A read-only element can be focused and copied but not changed. It is submitted and isn’t validated, like a native read-only input.

When the browser restores a page, for example on the back button, the elements get their values back like native controls.