A lightweight, flexible JavaScript library for dynamically adding and removing form fields with support for multiple groups and forms.
This library is specifically designed to work seamlessly with Webflow without any build process or dependencies. Simply add the script and start using dynamic fields in your Webflow projects!
1. Add the following as script in your page's before </body>
tag:
<!-- Include the dynamic fields script -->
<script src="https://cdn.jsdelivr.net/gh/sabernoori/dynamic-add-remove-fields@v3.0.0/src/dynamic-fields.js"></script>
<!-- Initialize DynamicFields / You can modify with your naming convention -->
<script>
document.addEventListener('DOMContentLoaded', function() {
new DynamicFields({
formId: 'wf-form-education', // Your Webflow form ID
groupName: 'education', // Match your data-group-name
fieldPrefix: 'education' // Prefix for field names
});
});
</script>
2. Create a form with desired input fields. Give your form a unique ID. You can do that In Form Settings β Element Settings β ID field, enter your form ID. (in our case we used wf-form-education
)
3. Inside the form, add a Div Block and Add class name whatever you want. Put inputs your need and configure them however you want.
Then do these In Element Settings β Custom Attributes:
- Name:
data-field-group
- Value: keep it empty
- Name:
data-group-name
- Value:
education
(or your preferred group name, we used this to seem like the example we have.)
4. Add Button elements for controlling the fields:
For the Add Button:
- Add a Button element for adding the fields
- Set button text to "Add Education" (or relevant text)
- In Element Settings β Custom Attributes:
- Name:
data-add-btn
- Value: keep it empty
- Name:
For the Remove Button:
- Add another Button element for removing the fields
- Set button text to "Remove"
- In Element Settings β Custom Attributes:
- Name:
data-remove-btn
- Value: keep it empty
- Name:
Complete Webflow HTML Structure Example:
<!-- This is what your Webflow structure should look like -->
<form id="wf-form-education" class="w-form">
<div data-field-group data-group-name="education">
<!-- Your input fields (these get cloned) -->
<input type="text" name="education-degree-1" placeholder="Degree" class="w-input">
<input type="text" name="education-school-1" placeholder="School" class="w-input">
<!-- Control buttons -->
<button type="button" data-add-btn class="w-button">Add Education</button>
<button type="button" data-remove-btn class="w-button">Remove</button>
</div>
</form>
5. Publish & Enjoy!
- β¨ Zero Dependencies - Pure vanilla JavaScript
- π― Multiple Groups - Support for different field groups within the same form
- π Multiple Forms - Manage fields across multiple forms simultaneously
- π§ Highly Configurable - Extensive customization options
- π¨ CSS Framework Agnostic - Works with any CSS framework
- π± Responsive - Mobile-friendly design
- π Built-in Validation - Optional field validation support
- π Debug Mode - Comprehensive logging for development
<script src="https://cdn.jsdelivr.net/gh/sabernoori/dynamic-add-remove-fields@v3.0.0/src/dynamic-fields.js"></script>
Download the dynamic-fields.js
file from the GitHub repository and include it in your project:
<script src="path/to/dynamic-fields.js"></script>
npm install dynamic-add-remove-fields
<form id="my-form">
<!-- Main container for the dynamic field group -->
<div class="field-group" data-group-name="education">
<!-- Initial fields (these will be cloned when adding new fields) -->
<input type="text" name="education-degree-1" placeholder="Degree">
<input type="text" name="education-school-1" placeholder="School">
<!-- Button to add more field sets (required class: add-field-btn) -->
<button type="button" class="add-field-btn">Add Education</button>
<!-- Button to remove current field set (required class: remove-field-btn) -->
<button type="button" class="remove-field-btn">Remove</button>
</div>
</form>
const dynamicFields = new DynamicFields({
formId: 'my-form',
groupName: 'education',
fieldPrefix: 'education',
maxFields: 5,
minFields: 1
});
Option | Type | Default | Description |
---|---|---|---|
formId |
string | 'default-form' |
ID of the target form |
groupName |
string | 'default' |
Name of the field group |
fieldPrefix |
string | 'field' |
Prefix for new field names |
maxFields |
number | 10 |
Maximum number of fields allowed |
minFields |
number | 1 |
Minimum number of fields required |
hideRemoveButtonWhenMinReached |
boolean | true |
Hide remove button when at minimum |
validateOnAdd |
boolean | false |
Validate fields before adding new ones |
enableDebugLogging |
boolean | false |
Enable console logging for debugging |
Perfect for simple scenarios like adding multiple education entries:
const education = new DynamicFields({
formId: 'registration-form',
groupName: 'education',
fieldPrefix: 'education',
maxFields: 5,
minFields: 1
});
Handle different types of fields in the same form:
// Education fields
const education = new DynamicFields({
formId: 'profile-form',
groupName: 'education',
fieldPrefix: 'education',
maxFields: 5
});
// Work experience fields
const work = new DynamicFields({
formId: 'profile-form',
groupName: 'work',
fieldPrefix: 'work-experience',
maxFields: 10
});
Same field type across different forms:
// Education in registration form
const regEducation = new DynamicFields({
formId: 'registration-form',
groupName: 'education',
fieldPrefix: 'reg-education',
maxFields: 3
});
// Education in profile form
const profileEducation = new DynamicFields({
formId: 'profile-form',
groupName: 'education',
fieldPrefix: 'profile-education',
maxFields: 5
});
Complex scenarios with different field types across multiple forms:
// Registration form - Education
const regEducation = new DynamicFields({
formId: 'registration-form',
groupName: 'education',
fieldPrefix: 'reg-education',
maxFields: 3
});
// Registration form - Work
const regWork = new DynamicFields({
formId: 'registration-form',
groupName: 'work',
fieldPrefix: 'reg-work',
maxFields: 5
});
// Profile form - Contacts
const profileContacts = new DynamicFields({
formId: 'profile-form',
groupName: 'contacts',
fieldPrefix: 'profile-contact',
maxFields: 3
});
// Profile form - Skills
const profileSkills = new DynamicFields({
formId: 'profile-form',
groupName: 'skills',
fieldPrefix: 'profile-skill',
maxFields: 10
});
- Form must have an
id
attribute - Field groups must have
data-group-name
attribute - Add buttons must have class
add-field-btn
- Remove buttons must have class
remove-field-btn
<form id="my-form">
<div class="field-group" data-group-name="education">
<!-- Source fields (will be cloned) -->
<input type="text" name="education-degree-1" placeholder="Degree">
<input type="text" name="education-school-1" placeholder="School">
<!-- Control buttons -->
<button type="button" class="add-field-btn">Add Education</button>
<button type="button" class="remove-field-btn">Remove</button>
</div>
</form>
new DynamicFields(options)
addField()
- Manually add a new fieldremoveField(fieldElement)
- Remove a specific fieldgetFieldCount()
- Get current number of fieldsvalidateFields()
- Validate all fields in the groupdestroy()
- Clean up event listeners and references
DynamicFields.createMultiple(configs)
- Create multiple instances at once
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- Internet Explorer 11+ (with polyfills)
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Run the test server to see examples in action:
npm run serve
Then visit:
http://localhost:8000/tests/scenario0-basic-single-group.html
http://localhost:8000/tests/scenario1-multiple-groups-single-form.html
http://localhost:8000/tests/scenario2-single-groups-multiple-forms.html
http://localhost:8000/tests/scenario3-multiple-groups-multiple-forms.html
See CHANGELOG.md for version history and changes.
This project is licensed under the MIT License - see the LICENSE file for details.
- π Documentation
- π Issue Tracker
- π¬ Discussions
Made with β€οΈ by the DynamicFields team