JB Design System form coordinator for validation, dirty checks, value collection, virtual fields, and nested forms.
- Validates JB form controls with one command.
- Tracks aggregate dirty state.
- Gets and sets values for named child controls.
- Supports native form controls, form-associated custom elements, virtual elements, and nested
jb-formelements. - Dispatches submit, dirty-change, and validity-change events.
Use jb-form when a group of fields needs aggregate validation, value collection, dirty-state tracking, virtual fields, or nested form sections.
Use a native <form> when you only need browser-native submission and do not need JB aggregate helpers.
npm i jb-formimport 'jb-form';<jb-form>
<jb-input name="name" required></jb-input>
<jb-button type="submit">Submit</jb-button>
</jb-form>| name | type | default | description |
|---|---|---|---|
name |
string |
"" |
Name used when this form is nested inside another jb-form. |
| name | type | readonly | description |
|---|---|---|---|
value |
FormValues |
no | Aggregated object of named child values. Setting it calls setFormValues(value). |
name |
string |
no | Name attribute value used by parent jb-form traversal. |
isDirty |
boolean |
yes | true when any named child control, virtual element, or sub-form is dirty. |
validation |
ValidationHelper<FormValues> |
yes | Aggregate jb-validation helper. |
validElements |
HTMLElement[] |
yes | Connected native and custom form controls registered directly under this jb-form. |
virtualElements |
object | yes | Virtual element registry: list, dictionary, add(config), and remove({ virtualElement }). |
subForms |
object | yes | Nested jb-form registry: list and dictionary. |
formElements |
FormElements |
yes | Internal native/custom child form element registry. |
| name | returns | description |
|---|---|---|
checkValidity() |
boolean |
Runs synchronous aggregate validation without showing errors. |
reportValidity() |
boolean |
Runs synchronous aggregate validation and asks children to show errors. |
jbCheckValidity({ showError }) |
Promise<CheckValidityAsyncResult> |
Runs rich async validation for jb-validation compatible children, virtual elements, and sub-forms. |
getValidationMessages() |
FormValidationMessages |
Returns validation messages for named child controls, virtual elements, and sub-forms. |
getValidationSummary() |
FormValidationSummary |
Returns validation summaries for named jb-validation compatible items. |
getValidationResult() |
FormValidationResult |
Returns full validation results for named jb-validation compatible items. |
getFormValues() |
FormValues |
Returns all named child values. Repeated names become TraverseCollection. |
getFormDirtyStatus() |
TraverseResult<boolean> |
Returns dirty status for named child controls, virtual elements, and sub-forms. |
setFormValues(value, shouldUpdateInitialValue?) |
void |
Sets values by name. Also updates initial values unless the second argument is false. |
setFormInitialValues(value, shouldUpdateValue?) |
void |
Sets initial values used for dirty checks. Also updates current values unless the second argument is false. |
| event | detail | description |
|---|---|---|
submit |
none | Dispatched after a trusted child submit is intercepted and reportValidity() returns true. |
dirty-change |
{ isDirty: boolean } |
Dispatched when aggregate dirty state changes. |
validity-change |
{ isValid: boolean } |
Dispatched when aggregate synchronous validity changes. |
change |
none | Dispatched by the form when a virtual element changes. Child controls may also bubble their own change events through jb-form. |
form-change |
none | Dispatched from a child control when setFormValues() changes it programmatically. |
init |
none | Dispatched from connectedCallback after child element scanning starts. |
disconnect |
none | Dispatched from disconnectedCallback. |
Use checkValidity() for a silent synchronous check and reportValidity() to show child validation messages.
const form = document.querySelector('jb-form');
const isValid = form.checkValidity();
const isValidAndShown = form.reportValidity();Use jbCheckValidity() when async validations are involved. It validates JB validation-compatible child controls, virtual elements, and sub-forms and returns a tree result with element references.
import { getInvalidElements } from 'jb-form';
const result = await form.jbCheckValidity({ showError: true });
const invalidElements = getInvalidElements(result);Detailed validation helpers:
form.getValidationMessages();
form.getValidationSummary();
form.getValidationResult();jb-form collects values from named direct child controls, virtual elements, and named sub-forms.
const form = document.querySelector('jb-form');
const values = form.getFormValues();
form.setFormValues({
name: 'Joe',
age: 10,
});
form.setFormValues({ name: 'Joe' }, false);setFormValues(value) updates both value and initialValue by default. Pass false as the second argument when you only want to change current values.
form.setFormInitialValues({ name: 'Joe', age: 10 });
form.setFormInitialValues({ name: 'Joe' }, false);console.log(form.isDirty);
console.log(form.getFormDirtyStatus());
form.addEventListener('dirty-change', (event) => {
console.log(event.detail.isDirty);
});jb-form listens for trusted submit events from submit-capable child controls, prevents the original event, calls reportValidity(), and dispatches its own submit event when the form is valid.
form.addEventListener('submit', (event) => {
event.preventDefault();
console.log(form.getFormValues());
});Use virtual elements for state that is not represented by a JB/native form control but still needs to participate in form values, dirty checks, or validation.
import { ValidationHelper } from 'jb-validation';
const tagList = form.virtualElements.add({
name: 'tags',
validation: new ValidationHelper({
getValue: () => tags,
getValidations: () => [
{
validator: (value) => value.length > 0,
message: 'Select at least one tag',
},
],
}),
getValue: () => tags,
getDirtyStatus: () => tags.length !== initialTags.length,
setValue: (value) => {
tags = value;
},
setInitialValue: (value) => {
initialTags = value;
},
});
tagList.dispatchOnChange();Remove a virtual element when it is no longer part of the form:
form.virtualElements.remove({ virtualElement: tagList });When two or more named items share the same name, the value becomes a TraverseCollection, which extends Map and is marked with ValueCollectionSymbol.
<jb-form>
<jb-input name="personName" value="Ali"></jb-input>
<jb-input name="phoneNumber" value="1234"></jb-input>
<jb-input name="phoneNumber" value="5678"></jb-input>
</jb-form>const values = form.getFormValues();
console.log(values.phoneNumber instanceof Map); // trueIf fields have id, the collection uses the id as the key; otherwise it uses numeric keys.
Nested jb-form elements can be managed individually and by a parent form.
<jb-form id="parentForm">
<jb-form name="profile">
<jb-input name="firstName"></jb-input>
</jb-form>
<jb-form name="security">
<jb-input name="password"></jb-input>
</jb-form>
</jb-form>console.log(document.querySelector('#parentForm').getFormValues());jb-form has a default slot for child controls and layout content. It does not currently expose CSS parts or CSS variables.
- See
jb-form/reactif you want to use this component in React. - See All JB Design System Component List for more components.
- Use Contribution Guide if you want to contribute to this component.
- Import
jb-formonce before using<jb-form>. - Put fields inside the default slot and give each field a
nameif its value should be collected. - Use
getFormValues()for aggregate values andsetFormValues(values)to update children by name. - Use
jbCheckValidity({ showError: true })for async validation;checkValidity()andreportValidity()are synchronous. - Listen to
submit,dirty-change, andvalidity-changefor form workflows. - Repeated names return
TraverseCollection, not a plain array. - Use
virtualElements.add(config)for non-DOM or non-standard form state. - This package includes
custom-elements.jsonand points to it with the package.jsoncustomElementsfield. The field is documented by the Custom Elements Manifest project in Referencing manifests from npm packages. - In
custom-elements.json,exports.kind: "js"describes JavaScript/TypeScript exports andexports.kind: "custom-element-definition"maps thejb-formtag name toJBFormWebComponent.