I had a need to do some fancy work on a MVC Razor page enabling and disabling buttons based on various criteria. To do this I needed to check to see if the user had changed any data on the page I ended up using the following structure to do it.
First set up your page with a form and all your input fields.
@using(Html.BeginForm("actionname", "controllername", new { area = "areaname" }, FormMethod.Post, new { id = "saveForm", @class = "disable-submit-form" })) { /* lots of page code */ }
This method serializes the data into a Name, Value array of objects and hashes it.
// Grab all the data fields in the code and serialize them, then hash them // @Html.Checkbox and CheckBoxFor need to be handled as a separate case function GetSerializedItems() { var serializedArray = $(".disable-submit-form").serializeArray() .filter(function (item) { return item.name != 'CheckboxItem1' && item.name != 'CheckboxItem2'; }); var serializedCheckboxItems = $('input:checkbox').map( function () { return { name: this.name, value: this.checked ? this.value : "false" }; }); for (var index = 0; index < serializedCheckboxItems.length; ++index) { serializedArray.push(serializedCheckboxItems[index]); } return convertSerializedArrayToHash(serializedArray); } $(document).ready(function () { // Get the initial state of the data on the page. var startItems = GetSerializedItems(); // On each field change recheck the current button state $('.disable-submit-form').on('change', function () { showhidebuttons(); }); function showhidebuttons() { var $form = $(".disable-submit-form"); var currentItems = GetSerializedItems(); var dirty = hashDiff(startItems, currentItems); var isDirty = countProperties(dirty) > 0; var isValid = $form.valid(); var isDraft = '@Model.IsDraft' === 'True'; $form.find(".submitform").attr('disabled', 'disabled'); if (isValid && isDirty) { $form.find(".submitform").removeAttr('disabled'); } else if (isDraft && isValid) { $form.find("#PreviewId").removeAttr('disabled'); $form.find("#PublishId").removeAttr('disabled'); } } } //Call ShowHideButtons to set the default state showhidebuttons();
Here are the javascript helpers I used.
function convertSerializedArrayToHash(a) { var r = {}; for (var i = 0; i < a.length; i++) { r[a[i].name] = a[i].value; } return r; } function hashDiff(h1, h2) { var d = {}; for (k in h2) { if (h1[k] !== h2[k]) d[k] = h2[k]; } return d; } function countProperties(obj) { var count = 0; for (var prop in obj) { if (obj.hasOwnProperty(prop)) ++count; } return count; }