Explain Codes LogoExplain Codes Logo

Generic way to detect if HTML form is edited

javascript
form-engineering
event-listeners
mutation-observers
Anton ShumikhinbyAnton Shumikhin·Dec 29, 2024
TLDR

Detect form modifications using JavaScript's addEventListener. Monitor input or change events to toggle a modified flag:

let isModified = false; document.querySelectorAll('form input, form select, form textarea').forEach((elem) => { elem.addEventListener('change', () => isModified = true); }); // Now, `isModified` indicates form changes.

The code hooks into all form elements, ensuring any data alteration flags the form as edited. This method is universal for text fields, dropdowns, checkboxes, etc. Use isModified to verify before actions like form submission.

Deep dive: Detailed form change detection

Beyond the basic mechanism of flagging on change, you may want to know what precisely has changed. Here's how to do a detail comparison:

let originalFormData = new FormData(document.querySelector('form')); function checkForChanges() { let currentFormData = new FormData(document.querySelector('form')); for(let key of originalFormData.keys()){ if(originalFormData.get(key) !== currentFormData.get(key)){ console.log(`Field ${key} seems to have developed a mind of its own. Definitely meddling human fingers here! 😅`); return true; } } return false; }

We capture the form state right at the beginning, and when checkForChanges is invoked, your form is compared with its original state. An important fingerprint of human meddling!

Enter stage: Hashing

When dealing with gigantic forms filled with numerous fields, hashing the form values using MD5 or SHA1 can make comparison more efficient. You go from comparing tons of values to just a simple string comparison:

function generateHash(formData) { // Example using MD5 return CryptoJS.MD5(formData).toString(); } let form = document.querySelector('form'); let originalHash = generateHash(new FormData(form).toString()); function formHasChanged() { let currentHash = generateHash(new FormData(form).toString()); // possesedFormAlert is ready to call Ghost Busters when changes occur 👻 let possessedFormAlert = originalHash !== currentHash; return possessedFormAlert; }

Consider this a form-exorcism. If the form goes from its innocent originalHash state to a possessed currentHash, you know what you're dealing with!

Interactive, Engaging UX

A step towards creating a top-notch user experience is alerting a user when they are about to navigate away without saving changes. Sure, unsaved spreadsheets may haunt their dreams, but we're here to keep that from happening:

window.addEventListener('beforeunload', function (e) { if (formHasChanged()){ e.preventDefault(); e.returnValue = ''; // Calling the ghostly prompt to ask users if they really intend to leave without saving. Spooky, but effective 👻! } });

This way, it's not just about passively detecting changes, but actively interacting with user actions to enhance user experience.

Robustness, Accessibility and... Immortality?

Let's make the detection solution universal: friendly towards different types of form controls, resilient to dynamic changes, and accessible across technologies:

Dynamic form handling

Forms can pull surprises like loading new fields dynamically or exist in single-page applications. To manage this, we enlist mutation observers for our quest:

let observer = new MutationObserver(() => { // This buddy walks in like a boss whenever the DOM stirs, ready to rebind event listeners or rehash the form }); observer.observe(document.querySelector('form'), {childList: true, subtree: true});

Change propagation

What about changes bubbling up from nested forms or components? Event bubbling to the rescue!

document.querySelector('form').addEventListener('input', (event) => { // Coding spider senses are tingling! Form has been modified });

This way, we strategically assign a single listener to the parent form and catch any mischief happening within!

Integration with modern frameworks

Remember that nifty libraries like Formik or React Hook Form offer built-in methods to handle states and changes. Seek out similar options for Vue, Angular, or your preferred battlefield.