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?
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});
});
});
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.
You could add an 'oldvalue' parameter to the input field. Populate this value at the time the page is generated either with JavaScript or on the server-side.
<input name="field1" value="10" oldvalue="10">
Then use the following function to serialize:
function serializeForm() {
data = "";
$("input,textarea").each(function (index, obj) {
if ($(obj).val() != $(obj).attr("oldvalue")) {
data += "&" + $(obj).serialize();
}
});
return data.substr(1);
}
After the data has been sent to the server, your script could update the 'oldvalue' parameters to prevent the data from being sent again unless a further change is made.