29

I want to know if a form has changed at all. The form can contain any form element, such as input, select, textarea etc. Basically I want a way to display to the user that they have unsaved changed made to a form.

How can I do this using jQuery?

To clarify: I want to catch ANY change to the form, not only to input elements but to all other form elements as well, textarea, select etc.

Weblurk
  • 6,562
  • 18
  • 64
  • 120

1 Answers1

85

The approach I usually take in such a case is that I check serialized form value. So the idea is that you calculate initial form state with $.fn.serialize method. Then when needed you just compare current state with the original serialized string.

To target all input elements (select, textarea, checkbox, input-text, etc.) within a form you can use pseudo selector :input.

For example:

var $form = $('form'),
    origForm = $form.serialize();

$('form :input').on('change input', function() {
    $('.change-message').toggle($form.serialize() !== origForm);
});
.change-message {
    display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
    <div class="change-message">You have unsaved changes.</div>
    <div>
        <textarea name="description" cols="30" rows="3"></textarea>
    </div>
    <div>Username: <input type="text" name="username" /></div>
     <div>
        Type: 
        <select name="type">
            <option value="1">Option 1</option>
            <option value="2" selected>Option 2</option>
            <option value="3">Option 3</option>
        </select>
    </div>
    <div>
        Status: <input type="checkbox" name="status" value="1" /> 1
        <input type="checkbox" name="status" value="2" /> 2
    </div>
</form>
dfsq
  • 191,768
  • 25
  • 236
  • 258
  • Great answer. Quesiton though, why doesn't this work without serializing? I mean, is there a way to do this without serializing? – Weblurk Nov 07 '14 at 08:17
  • 4
    Well you need a way to compare **all** form element values. I just found that serialization is very convenient way to do that. It's only one line of code. And this string only depends on input values, exactly what we need. It also properly work when user reverts changes. Serialized string also reverts to its original value. – dfsq Nov 07 '14 at 08:20
  • 2
    Works great. Thank you. – kwoxer Jan 05 '16 at 07:20
  • 1
    This is a great solution! A better solution than here: http://stackoverflow.com/questions/3025396/how-do-you-handle-a-form-change-in-jquery where they use data attribute, because solution like that is a one-way, once input changed, form will always stated as changed, while, this solution is two-way. If user input then deleting what he input, the form will not stated as changed because the serialize is matched. :) Doesn't it? – Taufik Nur Rahmanda Mar 09 '17 at 03:00
  • This works great! I had one issue where I had a tool that generated a random password and plopped it into the password fields, and that didn't register as a change... so I had to call .change() on those password fields after I updated their value (or you could call .trigger('change')), and it works great! – Gary Reckard Dec 28 '18 at 18:54
  • Great simple solution. Top Answer! – japes Sophey Mar 19 '20 at 16:21