Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable submit button unless original form data has changed

Tags:

html

jquery

css

Here's the code I am using:

$('form').bind('keyup change', function(){

The submit button is set to DISABLED by default, if something changes inside a input text field, or radio button check state or drop-down selection value, then the button must be set ENABLED by removing the disabled attribute.

My END GOAL: enter image description here

EDIT: If anything is changed back to its default value, the submit button shall be set to disabled by prop('disabled', true); - need some method to keep track of every change.

====================================================

Example: Go to Twitter, and sign-in, from the drop-down menu select Settings. In the Account Page, change your Username (just add an extra char), next scroll down, set a checkbox to checked, and change your country choice.

The button will be enabled at the bottom, go back and uncheck the checkbox you previously checked, the button at the bottom will remain enabled,

scroll to the top change your UserName back to what it was, scroll down the button to save changes will still be enabled, go to the country list and changed it back to what you previously had, now finally scroll down: the save changes button will be disabled.

====================================================

EDIT: this seems very similar, What is the best way to track changes in a form via javascript?

Quote: "You can render it disabled by default and have JavaScript handlers watching the inputs for change events to enable it. Maybe render some hidden fields or directly render JavaScript values to store the "originals" and, on those change events, check the current values against the originals to determine if the button should be enabled or disabled. – David Jan 18 at 15:14" (Enable 'submit' button only if a value in the form has been changed).

like image 818
John Smith Avatar asked May 16 '13 16:05

John Smith


4 Answers

I know this is a late answer, but this method uses far less code than the accepted answer without needing IDs on fields and without storing a global array.

Simply use .serialize() to store the data and check if it matches on each change.

http://jsfiddle.net/Pug3H/2/

$('form')
    .each(function(){
        $(this).data('serialized', $(this).serialize())
    })
    .on('change input', function(){
        $(this)             
            .find('input:submit, button:submit')
                .prop('disabled', $(this).serialize() == $(this).data('serialized'))
        ;
     })
    .find('input:submit, button:submit')
        .prop('disabled', true)
;
like image 135
Nigel Angel Avatar answered Oct 03 '22 16:10

Nigel Angel


You just need to save the orignal values and then check against them after every change.

Example: http://jsfiddle.net/justincook/42EYq/15/

JavaScript:

// Store original values
var orig = [];             
$("form :input").each(function () {
    var type = $(this).getType();
    var tmp = {'type': type, 'value': $(this).val()};
    if (type == 'radio') { tmp.checked = $(this).is(':checked'); }
    orig[$(this).attr('id')] = tmp;
});

// Check values on change
$('form').bind('change keyup', function () {
    var disable = true;
    $("form :input").each(function () {
        var type = $(this).getType();
        var id = $(this).attr('id');    
        if (type == 'text' || type == 'select') {
            disable = (orig[id].value == $(this).val());
        } else if (type == 'radio') {
            disable = (orig[id].checked == $(this).is(':checked'));
        }    
        if (!disable) { return false; } // break out of loop
    });

    $('#submit-data').prop('disabled', disable); // update button
});

// Get form element type
$.fn.getType = function () { 
    if(this[0].tagName == "INPUT")
        return $(this[0]).attr("type").toLowerCase() 
    else
        return this[0].tagName.toLowerCase();        
}

HTML:

<form id="" action="" method="post">
    <input type="text" value="Carl" name="firstname" id="firstname" />
    <input type="text" value="Johnson" name="lastname" id="lasttname" />
    <input id="radio_1" type="radio" value="female" name="sex" />Female
    <input id="radio_2" type="radio" value="male" name="sex" />Male
    <select id="country-list" name="countries">
        <option value="xx" selected="">Worldwide</option>
        <option value="in">India</option>
        <option value="us">United States</option>
    </select>
    <button id="submit-data" disabled="" type="submit">Save changes</button>
</form>
like image 25
Justin Avatar answered Oct 03 '22 15:10

Justin


An improved version of @Nigel Angel answer:

/* Disable the forms submissions until they have changed */
$(window).on('load', function (e) {
    $('form').each(function(){
        $(this).data('serialized', $(this).serialize())
    })
    .on('change input', function(){
        $(this).find(':submit, input[type="image"]')
            .prop('disabled', $(this).serialize() == $(this).data('serialized'));

        /* Check if input with type files has changed */
        var changedFiles = $( ":file" ).filter(function( index ) {
            return this.value != this.defaultValue;
        }).length;

        if ( changedFiles > 0) {
            $(this).find(':submit, input[type="image"]')
                .prop('disabled', false);
        }
    })
    .find(':submit, input[type="image"]').prop('disabled', true);
});
  • Added the input[type="image"] to the list of selectors that perform submission.
  • Added a check for changes of input with type file.
  • Also shortened the answer to use :submit to cover both cases of button and input.
like image 36
Amr Avatar answered Oct 03 '22 14:10

Amr


You can add a data-attribute to hold the default values - for checked types you can use 0 for unchecked and 1 for checked

<form id="" action="" method="post">
    <input type="text" data-default="Carl" value="Carl" name="firstname" id="firstname" />
    <input type="text" data-default="Johnson" value="Johnson" name="lastname" id="lasttname" />
    <br />
    <br />
    <input id="female" type="radio" value="female" name="sex" data-default="0" />Female
    <br />
    <input id="male" type="radio" value="male" name="sex" data-default="0" />Male
    <br />
    <br />
    <select id="country-list" name="countries" data-default="xx">
        <option value="xx" selected="">Worldwide</option>
        <option value="in">India</option>
        <option value="il">Israel</option>
        <option value="ru">Russia</option>
        <option value="us">United States</option>
    </select>
    <br />
    <br />
    <button id="submit-data" disabled="" type="submit">Save changes</button>
</form>

then in for your jquery use filter to get the ones that changed

var button = $('#submit-data');
$('form :input').not(button).bind('keyup change', function () {
    // get all that inputs that has changed
    var changed = $('form :input').not(button).filter(function () {
        if (this.type == 'radio' || this.type == 'checkbox') {
            return this.checked != $(this).data('default');
        } else {
            return this.value != $(this).data('default');
        }
    });
    // disable if none have changed - else enable if at least one has changed
    $('#submit-data').prop('disabled', !changed.length);
});

FIDDLE

like image 32
wirey00 Avatar answered Oct 03 '22 16:10

wirey00