If you want a quick guide for @formique/semantq, please visit:
Formique Semantq Guide
- About Formique
- Accessibility Compliance
- Key Features
- Why Choose Formique?
- Form Input Types Covered
- How to Write Form Schema
- Installation
- Full Vanilla JS Implementation
- Form Schema Example
- Invoking the Formique Class
- Complete List of Form Parameters
- Complete List of Form Settings
- Dynamic Drop-Down Schema
- Nested Conditionality Logic - Schema Definition
- Dynamic Fields with Repeater
- Styling the Form
- Form Submission API
- Google reCAPTCHA Integration
- Other Implementation Guides
- Contribute
- License
- Keywords
Formique is a robust and elegant WCAG and ARIA compliant form-building library tailored for JavaScript enthusiasts. It supports a wide array of input types, features JS-driven themes, and offers advanced functionalities like nested conditional logic and dynamic dropdowns. Highly customizable and extensible, Formique is built for the Semantq JS Framework but seamlessly integrates with Vanilla JS, React, Vue, Angular, and Svelte. Formique has three modes, the code mode (Schema Definition Language (SDL)), low code mode (Formique Form Definition Language (FFDL)) and the no code drag and drop mode.
Formique is Open-source & MIT licensed.
Formique is designed with a laser focus on WAI-ARIA and WCAG usability and accessibility, ensuring that the generated form HTML markup meets the highest standards of web accessibility.
With minimal declarative form input definitions, Formique takes care of the rest to ensure the final markup is comprehensive enough to meet official usability and accessibility standards.
For more information on the Web Content (Forms) Accessibility Guidelines (WCAG), you can visit the W3C website.
- Declarative Syntax: Define forms using a simple and intuitive schema.
- Low Code Syntax: Cut out the coding and technical jargon and write forms using easy and flexible low code syntax.
- Wide Range of Inputs: Supports text, email, number, password, date, time, file uploads, and more.
- Validation and Attributes: Easily specify validation rules and attributes for each form field.
- Dynamic Form Generation: Generate forms dynamically based on your schema.
- Framework Agnostic: Currently works with Semantq and vanilla JS. (More frameworks to be added)
- Accessibility and Usability Compliant: Formique yields form markup compliant with WCAG.
- Mobile Responsive: Forms are mobile responsive out of the box.
- Nested Dynamic Conditional Logic: Implement complex conditional logic to show or hide form fields based on user input.
- Dynamic Dropdowns: Create dropdowns whose options change dynamically based on other field selections.
- JavaScript-Driven Themes: Apply themes dynamically using JavaScript for a customizable user interface.
- WAI-ARIA and WCAG-Compliant HTML: Ensure all form elements are accessible and meet WCAG standards.
- Progressive Enhancement: Forms function with or without JavaScript, ensuring accessibility and functionality across all environments.
- Vanilla JS: No dependencies; works seamlessly with vanilla JS and Semantq JS framework. (More frameworks to be added)
- Lightweight: Minimal footprint optimized for performance.
- Customizable: Adapt the library to fit your project's unique needs for functionality and style.
- Declarative: Write your forms in JavaScript and define forms with a concise schema for better readability and maintainability.
- Usability and Accessibility Compliant: You just need to focus on defining form fields data. Formique handles WCAG compliance for you.
- Mobile Responsive: Formique forms are mobile responsive out of the box.
- Dynamic Features: Implement nested conditional logic, dynamic dropdowns, and JavaScript-driven themes to enhance user experience.
- Progressive Enhancement: Forms are designed to function with or without JavaScript, ensuring broad compatibility.
- Low Code Syntax: Cut out the coding and technical jargon and write forms using easy and flexible low code syntax.
- Text:
html <input type="text"> - Email:
html <input type="email"> - Number:
html <input type="number"> - Password:
html <input type="password"> - Telephone:
html <input type="tel"> - Date:
html <input type="date"> - Time:
html <input type="time"> - Datetime-local:
html <input type="datetime-local"> - Month:
html <input type="month"> - Week:
html <input type="week"> - URL:
html <input type="url"> - Search:
html <input type="search"> - Color:
html <input type="color"> - File:
html <input type="file"> - Hidden:
html <input type="hidden"> - Image:
html <input type="image"> - Textarea:
html <textarea> - Radio:
html <input type="radio"> - Checkbox:
html <input type="checkbox"> - Select (singleSelect & multipleSelect):
html <select> - Dynamic Single Select: Displays a single-select dropdown of subcategories based on a selected category. For example, it dynamically shows a dropdown of states when a country is selected from a list of countries:
html <select> - Submit:
html <input type="submit"> - html:
html <div class="formique-note"> <h3> </h3> <small> </small> </div>
The form schema is an array of field definitions. Each field is defined by an array containing:
- Input definition (required)
- Input validation (optional)
- Input attributes (optional, including binding attribute (optional)
- Options (applicable to single select, multiple select, radio and check box inputs)
- Type: The input type (e.g., 'text', 'email', 'radio').
- Name: The name attribute for the input.
- Label: The label for the input.
You don't need to use the type, name and label keys to define these parameters. Example Input Definition:
['text', 'firstname', 'First Name' ]
In the example above:
- The first item (text) defines the type of the input - this will yield:
<input type="text" ... - The second item (firstname) defines the name value of the input - this will yield:
<input name="firstname" ... - The third item (First Name) defines the Label value- this will yield:
<label for="firstname">First Name</label> - Final html output will be:
<div class="input-block" id="firstname-block">
<label for="firstname">First Name</label>
<input type="text" name="firstname" id="firstname" class="form-input" placeholder="First
Name">
</div>-
Validation: Object specifying validation rules. This can include:
- Required: Boolean to specify if the field is mandatory.
- Example:
required: true
- Example:
- Minlength: Specifies the minimum number of characters allowed.
- Example:
minlength: 5
- Example:
- Maxlength: Specifies the maximum number of characters allowed.
- Example:
maxlength: 50
- Example:
- Pattern: A regex pattern the input must match.
- Example:
pattern: "/^[A-Za-z0-9]+$/"
- Example:
- Min: Specifies the minimum numeric value allowed.
- Example:
min: 1
- Example:
- Max: Specifies the maximum numeric value allowed.
- Example:
max: 100
- Example:
- Step: Specifies the increment step for numeric values.
- Example:
step: 0.01(for decimal increments)
- Example:
- Required: Boolean to specify if the field is mandatory.
Formique will filter out any invalid validation defined and throw warnings on the browser console.E.g. when you define min and max validations (instead of minlength and maxlength) for a text field, Formique will filter these out.
- Attributes: Object specifying additional attributes like
id,class,style, etc.- Example:
{ id: 'username', class: 'form-input', style: 'font-size: 13px;' }
- Example:
- Binding: Optional binding syntax for dynamic data. The binding object has been moved to the attributes object, allowing for inclusion directly within the attributes. Two syntax formats are supported:
binding: '::nameOfField'binding: 'bind-value'- Example:
'::inputName'or'bind-value'
Note:inputNamemust be the value defined as the input name (the second item) in the input definition object.
- Options: For singleSelect,, multipleSelect, radio, and checkbox inputs. This is an array of options, each with a
valueandlabel.- Example:
[{ value: 'male', label: 'Male' }, { value: 'female', label: 'Female' }]
- Example:
For fields like singleSelect and multipleSelect you can also define default or pre selected options this way:
[{ value: 'red', label: 'Red' }, { value: 'blue', label: 'Blue', selected: true }]
In the example given: the blue option will be selected by default.
The 'html' input type allows you to inject arbitrary, static HTML directly into your form layout. This is useful for adding custom headings, informational notes, complex layouts, or decorative elements that aren't standard form fields.
[
'html', // 1. Type (required) — must be the string 'html'
'div', // 2. Wrapper Element Tag (required) — any valid HTML tag like 'div', 'section', 'span', etc.
'HTML Content', // 3. Inner Content (required) — can be a plain string or a mix of HTML tags and text
{}, // 4. Validation (required but ignored) — always use an empty object {}
{ // 5. Attributes (optional) — applied to the wrapper element defined in step 2
class: 'formique-note',
id: 'custom-note'
}
]Parameter Breakdown:
'html': The input type identifier.'div': The HTML tag for the wrapper element. The library will create this element. Replace'div'with'section','aside','span', etc., as needed.'<small><h3>Some Title</h3>Content</small>': The inner content of the wrapper element. This can be any valid string of HTML or plain text.{}: An empty object. Validation is not applicable, so this must be present but is ignored.{ class: 'formique-note', id: 'unique-id' }: Attributes for the wrapper element. You can include any valid HTML attributes likeclass,id,style,data-*attributes, etc.
This example creates an informational note box within the form:
const formSchema = [
// Other fields...
['text', 'username', 'Username', { required: true }],
// An HTML note explaining the password requirements
[
'html',
'div',
'<small><h3>Password Requirements</h3>Must be at least 8 characters, including one number and one special character.</small>',
{},
{ class: 'formique-note', style: 'margin-bottom: 1.5rem;' }
],
['password', 'password', 'Password', { required: true, minlength: 8 }],
// More fields...
];Rendered HTML Output:
The above schema will generate the following HTML structure inside your form:
<div class="formique-note" style="margin-bottom: 1.5rem;">
<small>
<h3>Password Requirements</h3>
Must be at least 8 characters, including one number and one special character.
</small>
</div>Important Notes:
- The
'html'type is for static content only. It is not a reactive input and does not have anameorvaluethat gets submitted with the form. - The third parameter (inner content) is injected as a raw HTML string, so be mindful of script injection risks if you are populating this with user-generated or untrusted data.
- All attributes defined in the fifth parameter are applied directly to the wrapper element you specify in the second parameter.
Formique supports dynamically repeatable field groups through the repeater field type. Users can add, remove, and nest groups of form fields at runtime—ideal for product variants, key-value metadata, or any variable-length form data.
['repeater', 'variants', 'Product Variants', {}, { minRows: 1, maxRows: 10 },
[
['text', 'sku', 'SKU Code', { required: true }],
['number', 'price', 'Price', { required: true, min: 0 }],
['repeater', 'images', 'Variant Images', {}, { maxRows: 5 },
['text', 'image_url', 'Image URL']
]
]
]['repeater', name, label, validation, config, blueprint]
// [0] [1] [2] [3] [4] [5]| Slot | Purpose |
|---|---|
[4] |
Repeater config: minRows, maxRows, addButtonText |
[5] |
Inner blueprint: field(s) to repeat (single field or array of fields) |
| Tier | Pattern | Use Case |
|---|---|---|
| 1. Simple List | Single field per row | Tags, emails, URLs |
| 2. Key-Value | 2–4 fields per row | Specifications, metadata |
| 3. Complex Blocks | Multi-field + nested repeaters | E-commerce variants, line items |
- No re-indexing on delete — row removal doesn't shift surviving field names
- Array gaps compacted at submission — clean, contiguous arrays for backend parsing
- Infinite nesting supported — repeaters can contain repeaters
Full documentation: Formique Repeater Specification
There are two primary ways to install and use Formique in your project:
-
Include the JavaScript before the closing
</body>tag of your HTML file:
```
**Note:** Formique now bundles its CSS internally. No separate stylesheet link is required — styles are injected automatically when the form initializes.
<details>
<summary><strong>⚠️ Deprecated: External CSS (versions prior to 1.2.4)</strong></summary>
If you are using an older version of Formique, you may need to include the CSS separately:
```html
<link rel="stylesheet" href="https://unpkg.com/formique-css@1.0.13/formique-css.css" />
```
This is no longer required from v1.2.4 onwards. Upgrade to the latest version to simplify your setup.
</details>
-
Include the JavaScript before the closing
</body>tag of your HTML file:<script src="https://cdn.jsdelivr.net/npm/formique@1.0.13/formique.umd.min.js"></script>
-
Define the form container somewhere in the HTML body:
<div id="formique"></div>
Alternatively, you can use a different container ID by setting
formContainerId: 'someelementid'in theformSettingsobject. -
Define your
formParams,formSchema, and initialize Formique in a<script>block (placed below the previous script tag):<script> const formSchema = [ ['text', 'name', 'Name', { required: true }, {}], ['email', 'email', 'Email', { required: true }, {}], ['singleSelect', 'diet', 'Dietary Requirements', { required: true }, {}, [ { value: 'gluten-free', label: 'Gluten-free' }, { value: 'vegetarian', label: 'Vegetarian' }, // Additional options here... ]], ['submit', 'submitButton', 'Submit'] ]; const formParams = { method: 'post', action: 'submit.js', id: 'myForm', class: 'form', style: 'width: 100%; font-size: 14px;' }; const formSettings = { requiredFieldIndicator: true, framework: 'semantq', placeholders: true, formContainerId: 'form-div' }; // Initialize the form const form = new Formique(formSchema, formSettings, formParams); </script>
Note: You can also use this instantiation with just the
formSchema, leaving out theformParamsandformSettings. This will apply the default dark theme and render the form inputs without the surrounding<form>element.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title> Formique Core - Full CDN Implementation </title>
<!-- Formique CSS for styling -->
<link rel="stylesheet" href="https://unpkg.com/formique-css@1.0.13/formique-css.css" />
<script src="https://cdn.jsdelivr.net/npm/formique@1.0.13/formique.umd.min.js"></script>
<!-- Initialize Formique via ES Module script -->
<script type="module">
/**
* Form schema definition containing all form fields and their configurations
* @type {Array<Array>}
*/
const formSchema = [
// Dynamic Single Select Field - Programming Languages
[
'dynamicSingleSelect', // Input type (required)
'languages', // Field name (required)
'Programming Scope(Dynamic Select)-Programming Languages', // Labels
{ required: true }, // Validation rules
{}, // Field attributes
// Dropdown Options
[
{
id: 'frontend', // Option group ID
label: 'Front End', // Option group label
options: [ // Frontend language options
{ value: 'javascript', label: 'JavaScript' },
{ value: 'html', label: 'HTML' },
{ value: 'css', label: 'CSS' },
{ value: 'typescript', label: 'TypeScript' },
{ value: 'semantq', label: 'Semantq' },
{ value: 'svelte', label: 'Svelte' },
{ value: 'vue', label: 'Vue' },
{ value: 'react', label: 'React' },
{ value: 'angular', label: 'Angular' },
]
},
{
id: 'backend', // Option group ID
label: 'Back End', // Option group label
options: [ // Backend language options
{ value: 'nodejs', label: 'Node.js' },
{ value: 'python', label: 'Python' },
{ value: 'java', label: 'Java' },
{ value: 'php', label: 'PHP' },
{ value: 'ruby', label: 'Ruby' },
{ value: 'csharp', label: 'C#' },
{ value: 'golang', label: 'Go' }
]
},
{
id: 'server', // Option group ID
label: 'Server', // Option group label
options: [ // Server/database options
{ value: 'mysql', label: 'MySql' },
{ value: 'supabase', label: 'Supabase' },
{ value: 'MongoDB', label: 'Mongodb' },
{ value: 'sqlite', label: 'SQlite' },
]
}
]
],
// Conditionality Fields - disppaly fields based on input of a specific field
[
'singleSelect',
'role',
'Role (Select Conference Presenter to see conditionality)',
{ required: true },
{ dependents: ['topic', 'mode'] }, // Fields that depend on this one
[
{ value: 'conference attendee', label: 'Conference Attendee' },
{ value: 'conference presenter', label: 'Conference Presenter' }
]
],
// Topic field - Text input (dependent on 'role' being 'conference presenter')
[
'text',
'topic',
'Topic',
{},
{
dependsOn: 'role',
condition: 'conference presenter' // (value) Simple string condition
}
],
// Mode field - Single Select (required, dependent on 'role')
[
'singleSelect',
'mode',
'Mode',
{ required: true },
{
dependsOn: 'role',
condition: (value) => value === 'conference presenter' // Function condition
},
[
{ value: 'physical', label: 'Physical' },
{ value: 'virtual', label: 'Virtual' }
]
],
// Standard input fields
['text', 'text_input', 'Text',{required: true},{'data-id': 'some-id'}],
['email', 'email_input', 'Email', {},{disabled: ''}], // boolean attributes
['number', 'number_input', 'Number',{required: true},{style: 'width: 100%;'}],
['password', 'password_input', 'Password'],
['tel', 'telephone_input', 'Telephone',{},{placeholder: '123-45-678', pattern: '[0-9]{3}-[0-9]{2}-[0-9]{3}'}],
['date', 'date_input', 'Date'],
['time', 'time_input', 'Time'],
['datetime-local', 'datetime_input', 'Datetime-local'],
['month', 'month_input', 'Month'],
['week', 'week_input', 'Week'],
['url', 'url_input', 'URL'],
['search', 'search_input', 'Search'],
['color', 'color_input', 'Color',{},{value: '#ff0056'}],
['file', 'file_input', 'File'],
['hidden', 'user_id', 'Hidden', {}, { value: '156' }], // Hidden field with preset value
['image', 'image_input', 'Image', {}, { src: 'some_image.png' }],
['textarea', 'textarea_input', 'Textarea', {}, { rows: '4', cols: '6' }],
// Radio button group
['radio', 'radio_input', 'Radio', {}, {}, [
{ value: 'male', label: 'Male' },
{ value: 'female', label: 'Female' },
{ value: 'other', label: 'Other' }
]],
// Checkbox group
['checkbox', 'checkbox_input', 'Checkbox', {}, {}, [
{ value: 'newsletter', label: 'Newsletter', selected: true },
{ value: 'updates', label: 'Updates' },
{ value: 'events', label: 'Events' }
]],
// Single select dropdown
['singleSelect', 'location', 'Select (Single Option with East selected)', {}, {}, [
{ value: 'east', label: 'East', selected: true },
{ value: 'south', label: 'South' },
{ value: 'north', label: 'North' }
]],
// Multiple select dropdown
['multipleSelect', 'diet', 'Diet (Multiple Select)', {}, {}, [
{ value: 'vegan', label: 'Vegan' },
{ value: 'vegetarian', label: 'Vegetarian' },
{ value: 'lacto-ovo', label: 'Lacto-ovo' }
]],
// Additional fields
['submit', 'submit_input', 'Submit'],
];
/**
* Form settings configuration
* @type {Object}
*/
const formSettings = {
theme: 'dark-blue', // [Optional] Name of visual theme
themeColor: '#da42f5', // [Optional] Overrides theme with a specific color
submitOnPage: true, // [Optional] If true, form submits without navigating away
//submitMode: 'email', // [Required if submitOnPage is true]
/* sendTo: [
'contacts@website.com',
'admin@someentity.com'
], // [Required if submitMode is 'email'] List of recipient emails
*/
//successMessage: 'Your registration details have been captured successfully!',
// [Optional] Custom message to show on successful submission
//errorMessage: 'There was an error in submitting your details. Please try again!',
// [Optional] Custom error message
//requiredFieldIndicator: true, // [Optional] Show an asterisk (*) for required fields
//framework: 'semantq', // [Optional] Enables syntax transformations for Semantq and CSRF handling for Laravel
//placeholders: true, // [Optional] If true, use labels as placeholders
formContainerId: 'myForm', // ID of the form wrapper (default is 'formique' - no need to define formContainerId here if the container element is 'formique')
//formContainerStyle: 'width: 100%; max-width: 700px; padding: 2rem;'
// [Optional] Inline style for the form container
validateBeforeSubmit: true, // When set to true, the submit button remains disabled until all required fields are properly filled. If a user attempts to click the disabled button, an alert reminds them to complete all required fields first.
};
/**
* Form parameters and attributes
* @type {Object}
*/
const formParams = {
method: 'POST', // [Required] HTTP method: 'GET' or 'POST'
//action: 'submit.php', // [Required] Form submission URL
//id: 'myForm', // [Optional] Unique form ID
//class: 'form', // [Optional] CSS class for styling
//framework: 'semantq', // [Optional] Enables Semantq syntax sugar (e.g., @change={handler})
//style: 'width: 100%; font-size: 14px;', // [Optional] Inline CSS styling for the <form> element
//enctype: 'multipart/form-data', // [Optional] Required for file uploads
//target: '_blank', // [Optional] Specifies where to display the response
//novalidate: true, // [Optional] Disable HTML5 validation
//accept_charset: 'UTF-8' // [Optional] Character set (will render as accept-charset)
};
// Instantiate and render the form
const form = new Formique(formSchema, formSettings, formParams);
</script>
</head>
<body>
<!-- Form container where Formique will inject the form -->
<div id="myForm" class="width-half"></div>
</body>
</html>When submit the filled form it will be submitted to the test POST api end point: https://httpbin.org/post - you can check the captured form data in your browser logs.
-
Install Formique via npm:
npm install formique
-
Import and Use Formique in Your JavaScript File:
import Formique from 'formique'; const formSchema = [ // Define your schema as shown above... ]; const formParams = { // Optional parameters... }; const formSettings = { // Optional settings... }; const form = new Formique(formSchema, formParams, formSettings);
Formique is also available in additional formats like ESM (ES Modules) and IIFE (Immediately Invoked Function Expression) for specific use cases. For most projects, we recommend using UMD for browser contexts and ESM for Node.js environments. Refer to the Formique CDN for all available formats.
Include the CSS and import Formique in the head section of your HTML file as shown above.
If you want use the provided CSS please include this CDN link in your page head section:
`
`- Define form container somewhere in the html body:
<div id="formique"></div>-
Define your form parameters (formParams), form schema (formSchema) and then initialize Formique in script which should go before the
html </body>tag.<script type="module"> import Formique from 'formique'; const formParams = { method: 'post', action: 'submit.js', id: 'myForm', class: 'form', semantq: true, style: 'width: 100%; font-size: 14px;' }; const formSchema = [ ['text', 'name', 'Name', { required: true }], ['email', 'email', 'Email', { required: true }], [ 'singleSelect', 'diet', 'Dietary Requirements', {required: true}, {}, [ {value: 'gluten-free', label: 'Gluten-free'}, {value: 'dairy-free', label: 'Dairy-free'}, {value: 'keto', label: 'Ketogenic'}, {value: 'low-carb', label: 'Low-carb'}, {value: 'pescatarian', label: 'Pescatarian'}, {value: 'halal', label: 'Halal'}, {value: 'kosher', label: 'Kosher'}, {value: 'vegetarian', label: 'Vegetarian'}, {value: 'lacto-ovo-vegetarian', label: 'Lacto-ovo-vegetarian'}, {value: 'raw-food', label: 'Raw food'}, {value: 'macrobiotic', label: 'Macrobiotic'}, {value: 'flexitarian', label: 'Flexitarian'} ] ], ['submit', 'submitButton', 'Submit'], ]; const form = new Formique(formParams, formSchema); </script>
Formique can be used as either a UMD module with a simple <script> tag or as an ESM module via npm.
Below is an example of a form schema that defines various input fields with validation, attributes, and options:
const formSchema = [
// Text Input Field
[
'text',
'firstName',
'First Name',
{ minlength: 2, maxlength: 5, required: true, disabled: true }, // Validation options
{ value: "John", id: 'firstNameInput', class: 'form-input', style: 'width: 100%;', oninput: "incrementer()" }, // Attributes
],
// URL Input Field
[
'url',
'websiteUrl',
'Website URL',
{ required: true }, // Validation options
{ id: 'websiteUrlInput', class: 'form-control', style: 'width: 100%;', binding: 'bind:value' }
],
// Radio Input Field
[
'radio',
'gender',
'Gender',
{ required: true }, // Validation options
{ id: 'genderRadio', class: 'form-radio-input', style: 'margin-left: 1rem;', onchange: 'actionFunction()' }
[
{ value: 'male', label: 'Male' }, // Options
{ value: 'female', label: 'Female' },
{ value: 'other', label: 'Other' }
]
],
// Checkbox Input Field
[
'checkbox',
'preferences',
'Preferences',
{ required: true }, // Validation options
{ id: 'preferencesCheckbox', binding: '::preferences', class: 'form-checkbox-input', style: 'margin-left: 1rem;', onchange: 'submit' }
[
{ value: 'news', label: 'Newsletter' }, // Options
{ value: 'updates', label: 'Product Updates' },
{ value: 'offers', label: 'Special Offers' }
]
],
// Single Select Input Field
[
'singleSelect',
'colors',
'Colors',
{ required: true }, // Validation options
{ id: 'colorsSelect', class: 'form-select-input', style: 'margin-left: 1rem;', onchange: 'trigger' }, // the onchange: 'trigger' format works with (framework: semantq) set in your formSettings object so that the syntax can be transformed as per framework specs
[
{ value: 'red', label: 'Red' }, // Options
{ value: 'green', label: 'Green' },
{ value: 'blue', label: 'Blue', selected: true }
]
],
// Multiple Select Input Field
[
'multipleSelect', // Type of field
'colors', // Name/identifier of the field
'Colors', // Label of the field
{ required: true, min: 2, max: 3 }, // Validation options
{ id: 'colorsSelect', class: 'form-select-input', style: 'margin-left: 1rem;', onchange: 'alerter' }
[
{ value: 'red', label: 'Red' }, // Options
{ value: 'green', label: 'Green' },
{ value: 'blue', label: 'Blue' },
{ value: 'yellow', label: 'Yellow' }
]
],
// Submit Button
[
'submit',
'submitButton',
'Submit',
{}, // Validation options
{ id: 'submitBtn', class: 'form-submit-btn', style: 'margin-top: 1rem; width: 100%;' }
]
];To create a form using Formique, you need to define the form parameters and schema. Below is an example of how to invoke the class with basic parameters, followed by a full list of possible parameters.
const formParams = {
method: 'post', // HTTP method (e.g., 'get', 'post')
action: 'submit.js', // Form submission URL
id: 'myForm', // Unique identifier for the form
class: 'form', // CSS class for styling
semantq: true, // Whether to use semantq HTML elements
style: 'width: 100%; font-size: 14px;' // Inline CSS styling
};const formParams = {
method: 'post', // HTTP method (e.g., 'get', 'post')
action: 'submit.js', // Form submission URL
id: 'myForm', // Unique identifier for the form
class: 'form', // CSS class for styling
framework: 'semantq', // this enables Semantq syntax sugar: i.e. attribute: onchange: 'handlerFunction' will be transformed to: @change={handlerFunction} if false or not defined completely the output would be regular html e.g.: onchange="handlerFunction()"
style: 'width: 100%; font-size: 14px;', // Inline CSS styling
enctype: 'multipart/form-data', // Encoding type for file uploads
target: '_blank', // Where to open the form result (e.g., '_self', '_blank')
novalidate: true, // Disable form validation
accept_charset: 'UTF-8' // this will be transformed to: accept-charset: 'UTF-8' Character set for form data
};- method: Specifies the HTTP method to use when submitting the form ('get', 'post').
- action: The URL where the form data will be submitted.
- id: A unique identifier for the form.
- class: CSS class names applied to the form for styling purposes.
- semantq: Boolean value to add syntax sugar in the Semantq JS Framework use case. If set event handler attributes will be rendered in the format: @click={incrementer}
- style: Inline CSS styling applied directly to the form element.
- enctype: Specifies how the form data should be encoded when submitted ('application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain').
- target: Specifies where to display the response after submitting the form ('_self', '_blank', '_parent', '_top').
- novalidate: Disables form validation when set to true.
- accept_charset: Specifies the character encoding used for form data submission.
By customizing these parameters, you can control various aspects of the form's behavior and appearance.
The formSettings object allows you to customize the behavior and appearance of your form. Below is a comprehensive list of all possible settings:
const formSettings = {
// --- Appearance ---
theme: "dark-blue", // Form theme: see section below on complete list of themes
themeColor: '#4338ca', // Overrides theme with a specific hex color for buttons and focus states
formContainerStyle: 'width: 100% !important; max-width: 700px; padding: 2rem;', // Inline styles for the form container
requiredFieldIndicator: true, // Display asterisk (*) for required fields
placeholders: true, // Use labels as placeholders inside input fields
disableStyles: false, // Set to true to prevent Formique from injecting internal CSS
// --- Submission ---
submitOnPage: true, // Enable form submission on the same page without navigation
submitMode: 'email', // Submission mode: 'email' or 'rsvp' (requires submitOnPage: true)
sendTo: [ // Recipient email(s) — required if submitMode is 'email' or 'rsvp'
'contacts@website.com',
'admin@someentity.com'
],
validateBeforeSubmit: true, // Disable submit button until all required fields are valid
// --- Messages ---
successMessage: "Your registration details have been captured successfully!", // Custom success message
errorMessage: "There was an error in submitting your details. Please try again!", // Custom error message
// --- RSVP (requires submitMode: 'rsvp') ---
registrantMessage: 'Hi {name}, thanks for registering!', // RSVP confirmation message (supports {fieldName} placeholders)
registrantSubject: 'RSVP Confirmation', // Subject line for RSVP email
emailField: 'email', // Field name that contains the registrant's email
sendFrom: 'noreply@yourdomain.com', // Sender email address for RSVP emails
subject: 'Message From Contact Form', // Subject line for notification emails
// --- reCAPTCHA ---
recaptchaSecretKey: 'your_secret_key_here', // Secret key for server-side reCAPTCHA verification
// --- Redirect ---
redirect: true, // Enable redirect after successful submission
redirectURL: 'https://example.com/thank-you', // URL to redirect to
// --- Container ---
formContainerId: 'form-div', // Target container by ID (default is 'formique')
// --- Framework ---
framework: 'semantq', // Specify framework for syntax transformations (e.g., 'semantq', 'svelte','react','vue')
};-
theme: Defines the appearance of the form. Options include
"dark-blue","light", and more, allowing for customization based on your application's UI. -
submitOnPage: Controls whether the form submission should happen on the same page (
true) - omit if you don't need this feature. -
successMessage: The message displayed to the user after a successful form submission in the context of enabled submitOnPage. This can be customized to fit the context of the form. If submitOnPage is enabled and the successMessage parameter is not defined, Formique will display the default success message upon form submission: "Your details have been submitted successfully!"
-
errorMessage: The message displayed when there is an error in form submission. The actual JSON response error is appended for detailed feedback. If submitOnPage is enabled and the errorMessage parameter is not defined, Formique will display the default error message upon form submission: "An error occurred while submitting the form. Please try again."
-
requiredFieldIndicator: When set to
true, a red asterisk (*) will appear next to fields marked as required, helping users easily identify mandatory fields. -
framework: Specifies the front-end framework used, such as
'semantq','svelte','vue','angular', or'react'. If you are not using any framework, this parameter can be omitted. -
placeholders: Enables labels to be shown as placeholders inside input fields, providing a cleaner look and saving space.
-
formContainerId: Allows targeting a specific container by its ID where the form will be rendered. If the container ID is
'formique', this parameter can be omitted. -
validateBeforeSubmit: When set to
true, the submit button remains disabled until all required and visible form fields pass HTML5 validation. The button becomes clickable only once every required field is properly filled. If a user attempts to click the disabled button, an alert appears with the message "Fill all the required details before you submit." Hidden fields (those controlled by conditional logic viadependsOn) are automatically excluded from the validation check. If this parameter is omitted or set tofalse, the submit button is always enabled and relies on the browser's default validation behavior. -
themeColor: Overrides the predefined theme's button background and input focus border color with a custom hex value. This takes priority over the
themesetting and is useful when you need to match your brand colors without creating a custom theme. Example:themeColor: '#4338ca'. -
disableStyles: When set to
true, Formique will not inject its internal CSS styles into the page. Use this option when you want to provide your own complete stylesheet and avoid any style conflicts. If this parameter is omitted, internal styles are injected automatically. -
formContainerStyle: Applies custom inline CSS styles directly to the form container element. This gives you the highest specificity for controlling the container's appearance, such as width, padding, margins, or any other CSS property. Example:
formContainerStyle: 'width: 100% !important; max-width: 700px; padding: 2rem;'. -
submitMode: Determines how the form submission is handled when
submitOnPageis set totrue. Available options are'email'(sends form data to the email addresses specified insendTo) and'rsvp'(sends the notification email plus a confirmation email to the registrant). If this parameter is omitted, the form uses the default on-page submission behavior without email handling. -
sendTo: An array of email addresses that will receive the form submission data. This parameter is required when
submitModeis set to'email'or'rsvp'. Supports multiple recipients. Example:sendTo: ['info@website.com', 'admin@website.com']. -
registrantMessage: The confirmation message body sent to the registrant when
submitModeis set to'rsvp'. Supports dynamic placeholders using{fieldName}syntax, which will be replaced with the actual form field values. Example:registrantMessage: 'Hi {name}, thanks for registering for {event}!'. -
registrantSubject: The subject line for the RSVP confirmation email sent to the registrant when
submitModeis set to'rsvp'. If omitted, defaults to'RSVP Confirmation'. -
emailField: Specifies the name of the form field that contains the registrant's email address. Required when
submitModeis set to'rsvp'so Formique knows which field to use for sending the confirmation. Example:emailField: 'email'. -
sendFrom: The sender email address used for RSVP confirmation emails when
submitModeis set to'rsvp'. If omitted, defaults to'noreply@yourdomain.com'. -
subject: The subject line for notification emails sent to the recipients listed in
sendTo. Supports static text. If omitted, Formique will first check for a form field named "subject" and use its value, or fall back to'Message From Contact Form'. -
recaptchaSecretKey: The Google reCAPTCHA secret key used for server-side verification. Required when a
recaptchafield is included in the form schema. This key must match the site key used in the reCAPTCHA field attributes. -
redirect: When set to
true, the page will redirect to the URL specified inredirectURLafter a successful form submission. If omitted, no redirect occurs and the success message is displayed on the same page. -
redirectURL: The target URL for post-submission redirects. Only used when
redirectis set totrue. Example:redirectURL: 'https://example.com/thank-you'.
All settings are optional: You can use only the settings that are relevant to your needs or set up.
When set to true, the submit button remains disabled until all required fields are properly filled. If a user attempts to click the disabled button, an alert reminds them to complete all required fields first.
| Setting | Submit Button State | Click Behavior |
|---|---|---|
validateBeforeSubmit: true |
Disabled until all required fields pass HTML5 validation | Alert: "Fill all the required details before you submit." |
validateBeforeSubmit: false or omitted |
Always enabled | Submits normally (browser validation still applies) |
- The button is disabled on page load
- Formique listens for
inputandchangeevents across the entire form - After every change, it checks if all visible required fields pass HTML5 validation
- Hidden dependency fields (those controlled by conditional logic) are automatically skipped
- Once every required field is valid, the button becomes enabled
- If a user clears a required field, the button returns to a disabled state
const formSettings = {
validateBeforeSubmit: true, // Enables submit validation
theme: 'blue',
submitOnPage: true,
};
const formParams = {
method: 'POST',
};
const form = new Formique(formSchema, formSettings, formParams);<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Formique - Submit Validation Example</title>
</head>
<body>
<div id="formique" class="width-full"></div>
<script type="module">
import Formique from './formique-semantq-patch.js';
const formSchema = [
['text', 'name', 'Name', { required: true }, {}],
['text', 'slug', 'Slug', { required: true }, {}],
['text', 'description', 'Description', { required: true }, {}],
['file', 'cv', 'Upload CV', { required: true }, {}],
['submit', 'submit', 'Submit']
];
const formSettings = {
validateBeforeSubmit: true,
theme: 'blue',
submitOnPage: true,
};
const formParams = {
method: 'POST',
};
const form = new Formique(formSchema, formSettings, formParams);
console.log('Formique initialized with submit validation enabled');
</script>
</body>
</html>- Only visible fields are validated. Fields hidden by conditional logic (
dependsOn) are automatically excluded from the validation check - The validation uses the browser's built-in HTML5 constraint validation API (
checkValidity()) - Works alongside other
formSettingsoptions likesubmitOnPage,submitMode, andrequiredFieldIndicator - The alert message is currently built-in; customization support is planned for a future release
Default Invocation: Just like the formParams object, if no formSettings object is provided, you can simply initialize Formique with the form schema as follows:
const form = new Formique(formSchema);To implement Formique in your Svelte project please follow this guide: [https://www.npmjs.com/package/svelte-formique](Svelte Formique guide).
<div id="formique">
<form
method="post"
action="submit.js"
id="myForm"
class="form"
semantq
style="width: 100%; font-size: 14px;"
>
<div class="input-block">
<label for="firstNameInput">First Name</label>
<input
type="text"
name="firstName"
bind:value="firstName"
id="firstNameInput"
value="John"
class="form-input"
style="width: 100%;"
@input={incrementer}
minlength="2"
maxlength="5"
required
disabled
/>
</div>
<div class="input-block">
<label for="websiteUrlInput">Website URL</label>
<input
type="url"
name="websiteUrl"
bind:value="websiteUrl"
id="websiteUrlInput"
class="form-control"
style="width: 100%;"
required
/>
</div>
<fieldset class="radio-group">
<legend>Gender</legend>
<div>
<input
type="radio"
name="gender"
value="male"
bind:value="gender"
class="form-radio-input"
style="margin-left: 1rem;"
@change={actioner}
id="genderRadio-male"
/>
<label for="genderRadio-male">Male</label>
</div>
<div>
<input
type="radio"
name="gender"
value="female"
bind:value="gender"
class="form-radio-input"
style="margin-left: 1rem;"
@change={actioner}
id="genderRadio-female"
/>
<label for="genderRadio-female">Female</label>
</div>
<div>
<input
type="radio"
name="gender"
value="other"
bind:value="gender"
class="form-radio-input"
style="margin-left: 1rem;"
@change={actioner}
id="genderRadio-other"
/>
<label for="genderRadio-other">Other</label>
</div>
</fieldset>
<fieldset class="checkbox-group">
<legend>Preferences</legend>
<div>
<input
type="checkbox"
name="preferences"
value="news"
bind:checked="preferences"
class="form-checkbox-input"
style="margin-left: 1rem;"
@change={submit}
id="preferencesCheckbox-news"
/>
<label for="preferencesCheckbox-news">Newsletter</label>
</div>
<div>
<input
type="checkbox"
name="preferences"
value="updates"
bind:checked="preferences"
class="form-checkbox-input"
style="margin-left: 1rem;"
@change={submit}
id="preferencesCheckbox-updates"
/>
<label for="preferencesCheckbox-updates">Product Updates</label>
</div>
<div>
<input
type="checkbox"
name="preferences"
value="offers"
bind:checked="preferences"
class="form-checkbox-input"
style="margin-left: 1rem;"
@change={submit}
id="preferencesCheckbox-offers"
/>
<label for="preferencesCheckbox-offers">Special Offers</label>
</div>
</fieldset>
<fieldset class="form-select">
<label for="colorsSelect">Colors</label>
<select
name="colors"
bind:value="colors"
id="colorsSelect"
class="form-select-input"
style="margin-left: 1rem;"
@change={trigger}
required
>
<option value="">Choose an option</option>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue" selected>Blue</option>
</select>
</fieldset>
<fieldset class="form-select">
<label for="colorsSelect">Colors</label>
<select
name="colors"
bind:value="colors"
id="colorsSelect"
class="form-select-input"
style="margin-left: 1rem;"
@change={alerter}
required
multiple
>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
<option value="yellow">Yellow</option>
</select>
</fieldset>
<input
type="submit"
id="submitBtn"
value="Submit"
class="form-submit-btn"
style="margin-top: 1rem;"
/>
</form>
</div>The dynamicSingleSelect input type in Formique is used for generating dynamic dropdowns based on predefined options. It allows you to define multi-level select options (e.g., categories and subcategories) that change based on user selections. Below is an example of the schema format for implementing dynamic drop-downs.
- Country-State Dropdowns: A common implementation where selecting a country dynamically updates the list of states/provinces.
- Product Categories: A dropdown where the first selection (e.g., a product category) updates the second dropdown to show relevant product subcategories.
- Job Roles & Departments: Selecting a department dynamically shows job roles related to that department (e.g., selecting "IT" shows job roles like "Software Developer", "Network Engineer", etc.).
- Course & Subjects: In educational systems, choosing a course can display relevant subjects or modules available for that course.
- Location-Based Services: When selecting a country or city, a second dropdown can list local services or offices relevant to the location chosen.
The code below goes into your
[
'dynamicSingleSelect', // Input type (required)
'languages', // Field name (required)
'Programming Scope-Programming Languages', // Labels for both primary drop down and secondary (dynamic) drop down seperated by a hyphen - e.g. Country-States
{ required: true }, // Validation rules (optional) but the curly braces {} must always be included
{}, // Field attributes (optional) but the curly braces {} must always be included
// Dropdown Options
[
{
id: 'frontend', // Option group ID (required)
label: 'Front End', // Option group label (required)
options: [ // List of options (required)
{ value: 'javascript', label: 'JavaScript' },
{ value: 'html', label: 'HTML' },
{ value: 'css', label: 'CSS' },
{ value: 'typescript', label: 'TypeScript' },
{ value: 'semantq', label: 'Semantq' },
{ value: 'svelte', label: 'Svelte' },
{ value: 'vue', label: 'Vue' },
{ value: 'react', label: 'React' },
{ value: 'angular', label: 'Angular' },
]
},
{
id: 'backend', // Option group ID (required)
label: 'Back End', // Option group label (required)
options: [ // List of options (required)
{ value: 'nodejs', label: 'Node.js' },
{ value: 'python', label: 'Python' },
{ value: 'java', label: 'Java' },
{ value: 'php', label: 'PHP' },
{ value: 'ruby', label: 'Ruby' },
{ value: 'csharp', label: 'C#' },
{ value: 'golang', label: 'Go' }
]
}
]
]Formique allows for dynamic form generation with powerful conditional logic based on the values of other form fields. This allows you to create forms where the options in one field depend on the selection made in another field.
- Dynamic Field Display: Show or hide fields based on previous selections.
- Conditional Logic: Use conditions such as specific values in other fields to control the availability of options or visibility of fields.
- Multiple Dependencies: Fields can have more than one dependents
The following schema demonstrates how to implement dynamic dropdowns with nested conditional logic in Formique.
[
// Role field - Single Select (required)
['singleSelect', 'role', 'Role', { required: true }, { dependents: ['topic', 'mode'] },
// in the attributes object of the parent field add dependents (array) by field names to the dependents: item
[
{ value: 'conference attendee', label: 'Conference Attendee' },
{ value: 'conference presenter', label: 'Conference Presenter' }
]
],
// Topic field - Text input (dependent on 'role' being 'conference presenter')
['text', 'topic', 'Topic', {}, { dependsOn: 'role', condition: 'conference presenter' }],
// in the attributes object of the child field add the dependsOn: 'role' item where the key is dependsOn: and the value is name of the parent field: e.g. 'role in this case'
// also add the condition this way: condition: 'conference presenter'
// you can use the string 'conference presenter' as the condition to be met
// so this if the user select Conference Presenter in the role field - then dependents of that field (mode and topic) will be displayed. If the selected is changed to something else that doesn't meet the defined condtion - the dependents will be hidden.
// Mode field - Single Select (required, dependent on 'role' being 'conference presenter')
['singleSelect', 'mode', 'Mode', { required: true }, { dependsOn: 'role', condition: (value) => value === 'conference presenter' }, // you can use an arrow function to evaluate the condition - this is useful for more comprex evaluations
[
{ value: 'physical', label: 'Physical' },
{ value: 'virtual', label: 'Virtual' }
]
]
]Formique provides a robust and flexible system for styling forms, offering built-in themes, CSS classes for various components, and options for fine-grained customization of both form elements and the form container.
Formique offers several ways to style form elements, from predefined themes to custom CSS.
Formique includes a set of headless and minimal built-in themes primarily affecting the submit button background and the bottom border of focused inputs. Most themes maintain a light background, with the dark theme being an exception as it offers full dark background support.
Available Themes:
lightdarkpinkindigodark-bluelight-bluedark-orangebright-yellowgreenpurplemidnight-blushdeep-bluebluebrownorange
To apply a theme, set the theme option in your formSettings object. If no theme is specified, Formique defaults to the dark theme.
const formSettings = {
theme: 'indigo' // Example: Applies the 'indigo' theme
};For precise control over the button and focus colors, use the themeColor option with a hexadecimal value.
const formSettings = {
themeColor: '#327ba8' // Overrides the button and focus color
};Formique provides a set of default CSS classes for various form components, enabling consistent styling. These classes are predefined in the formique.css stylesheet, which developers can use directly or as a reference for custom CSS.
| Form Component | Default Class Name |
|---|---|
Wrapper (div) for Inputs |
input-block |
| Input Fields | form-input |
| Radio Button Groups | radio-group |
| Checkbox Groups | checkbox-group |
| Select Dropdowns | form-select |
You can override the default input class by defining your preferred class name within the input attributes object, e.g., { class: 'form-control' }.
Formique exposes its internal CSS classes, allowing for complete customization. You can target the form using .formique and individual elements with classes like .formique-input, .formique-label, and .formique-submit.
.formique-input {
border-radius: 5px;
padding: 10px;
}Formique renders within a container <div>, which offers flexible styling and sizing options.
By default, Formique uses a <div> with the ID formique:
<div id="formique" class=""></div>You can specify a custom container ID using the formContainerId option in your formSettings:
const formSettings = {
formContainerId: 'myForm'
};And in your HTML:
<div id="myForm"> Your Form will be displayed here </div>Formique includes responsive width utility classes that can be applied directly to your form container:
| Class Name | Description |
|---|---|
width-full |
100% width |
width-half |
50% width |
width-medium |
600px fixed width |
width-small |
400px fixed width |
Example:
<div id="formique" class="width-half"></div>For precise control over the container's inline styling, use the formContainerStyle setting. This will directly override the container's style attribute.
const formSettings = {
formContainerStyle: 'width: 100%; max-width: 700px; padding: 2rem;'
};Below is an alphabetically grouped list of all unique CSS class selectors used in Formique for comprehensive customization:
.formique.formique-form.width-custom.width-full.width-half.width-medium.width-small
.form-checkbox-input.form-control.form-input.form-label.form-radio-input.form-select.form-select-input.form-textarea
.checkbox-group.input-block.radio-group
For testing purposes, you can define the method as "POST" in the formParams object. This allows you to simulate and test form submissions using Formique's built-in functionality.
const formParams = {
method: "POST",
// other params
};-
Omit the
actionparameter in theformSettings. This way, Formique will serialize the form data upon submission and send it to thehttps://httpbin.org/postendpoint. -
Console Logging: The response, along with the actual form data, will be logged in the browser's console, allowing you to review and verify the submission process.
-
Fetch API-Based Form Submission: By omitting the
actionparameter, Formique uses the Fetch API to send the form data tohttps://httpbin.org/post. This sets up a functional testing environment where you can observe the data handling without needing an immediate backend setup. -
Transition to Custom Endpoints: Once you've tested the form submission, you can define your own
actionURL or endpoint in theformParamsobject. This allows you to direct the form data to your specified backend and handle it according to your application's needs.
const formParams = {
method: "POST", // OR GET, ETC
action: "https://your-custom-endpoint.com/submit"
};This approach helps you smoothly transition from testing to production, giving you control over where and how your form data is processed.
With Formique, you can use the Formique cloud-based API to handle form submissions.
This means:
- No backend server logic is required
- Formique takes care of sending emails
- You simply deploy the form and configure the right parameters
Define your form fields using formSchema as shown earlier in the docs.
const formSchema = [
['text', 'name', 'Name', { required: true }],
['text', 'surname', 'Surname', { required: true }],
['email', 'email', 'Email', { required: true }],
['text', 'message', 'Message', { required: true }],
['recaptcha', 'recaptcha', 'Please verify you are human', { required: true }, {
siteKey: 'site_key_here',
version: 'v2'
}],
['submit', 'submit', 'Submit'],
];Customize how the form behaves using formSettings.
const formSettings = {
recaptchaSecretKey: 'recaptcha_secret_key', // Optional if you're using reCAPTCHA
submitOnPage: true, // Submits directly from the page
submitMode: 'email', // Other available mode: 'rsvp'
sendTo: ['info@yourwebsite.com'] // Supports multiple recipients
};email: Sends form submission to specified email(s)rsvp: Sends confirmation email to the registrant as well
Basic request parameters used during form submission.
const formParams = {
method: 'POST',
};If you want to implement Google reCAPTCHA, remember to include the following script in the <head> section of your HTML page:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>This script is required to load and render the reCAPTCHA widget on your form.
In addition to external stylesheets, individual form elements can be styled directly via attributes specified in the form schema. This allows for fine grained control (inline styling) over the appearance of each element.
For non-technical users, see the Formique Low Code Guide.
For Vue-specific integration details, check out the Vue.js Guide.
Formique is an open-source project. Contributions, issues, and feature requests are welcome!
Formique is licensed under the MIT License.
Javascript forms, declarative form syntax, js form library, formique View Formique Complete CDN Implementation - All Fields
