Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select/submit only changed form fields with jQuery

I'm looking for a way to submit only changed form fields to the server. So, let's say I have a form

<form>
    <input type="text" name="a"/>
    <select name="b">...</select>
    <input type="checkbox" name="c"/>
</form>

which is populated with certain data already. The user edits the form and clicks submit. If the user only changed input b, then I want to submit only input b. If only a and c were changed, I want to submit only a and c. And so on.

I could write something myself to accomplish this, but I am wondering maybe there is already something out there that I could use? Ideally, I would like the code to be short. Something like this would be perfect:

$('form').serialize('select-only-changed');

Also, I came across this http://code.google.com/p/jquery-form-observe/ , but I see there are issues with it. Is this plugin working solidly?

like image 962
Dimskiy Avatar asked Mar 07 '11 15:03

Dimskiy


2 Answers

Another approach would be to serialize the form when the page loads, and then on submit, only submit the changes.

$(function() {

  var $form = $('form');

  var startItems = convertSerializedArrayToHash($form.serializeArray()); 

  $('form').submit() {
    var currentItems = convertSerializedArrayToHash($form.serializeArray());
    var itemsToSubmit = hashDiff( startItems, currentItems);

    $.post($form.attr('action'), itemsToSubmit, etc.
  }
});

Then, all you have to write is the hashDiff function, which is straightforward and generally useful.

This is nice because it can easily be packaged into a plugin, and it can work repeatedly on the same form if you're using Ajax.

function hashDiff(h1, h2) {
  var d = {};
  for (k in h2) {
    if (h1[k] !== h2[k]) d[k] = h2[k];
  }
  return d;
}

function convertSerializedArrayToHash(a) { 
  var r = {}; 
  for (var i = 0;i<a.length;i++) { 
    r[a[i].name] = a[i].value;
  }
  return r;
}

Here's a minimal test:

  describe('hashDiff()', function() {
    it('should return {} for empty hash',function() {
      expect(hashDiff({},{})).toEqual({});
    });
    it('should return {} for equivalent hashes',function() {
      expect(hashDiff({a:1,b:2,c:3},{a:1,b:2,c:3})).toEqual({});
    });
    it('should return {} for empty hash',function() {
      expect(hashDiff({a:1,b:2,c:3},{a:1,b:3,c:3})).toEqual({b:3});
    });
  });
like image 160
ndp Avatar answered Oct 06 '22 01:10

ndp


Another option would be to mark the fields as disabled before they are submitted. By default disabled fields will not be serialized or submitted with a default form post.

Simple example:

function MarkAsChanged(){
    $(this).addClass("changed");
}
$(":input").blur(MarkAsChanged).change(MarkAsChanged);

$("input[type=button]").click(function(){
    $(":input:not(.changed)").attr("disabled", "disabled");
    $("h1").text($("#test").serialize());
});

on jsfiddle.

like image 31
Mark Coleman Avatar answered Oct 06 '22 01:10

Mark Coleman