maxatwork / form2js

Javascript library for collecting form data
http://maxatwork.github.com/form2js/
MIT License
639 stars 137 forks source link

Asp.Net MVC checkboxes special case #35

Open michael-lang opened 12 years ago

michael-lang commented 12 years ago

When an Asp.net MVC 3 view helper spits out a checkbox it puts a checkbox and a hidden text field in the html. This is to ensure that a value is passed back in a post even when the checkbox is not checked. The model binder on the server needs all the properties to have a value to ensure the proper model is bound, and thus the proper controller action method is invoked.

<input type="checkbox" value="true" name="IsFavorite" id="IsFavorite" />
<input type="hidden" value="false" name="IsFavorite"/>

So now the name/value pairs that are generated contain two values for the check box when it is checked, true and false. And false is the second value. So later in processNameValues the last value in wins.

A possible solution is to filter out duplicate values for check boxes. here is the relevant jQuery code I came up with. This generates my name/value list that I then pass into a modified version of your processNameValues function that takes in a json object to update instead of creating a new one. See issue #34.

function updateJson(form, json) {
    var arr = $(form).find(":input, :radio")
        .filter(function () {
            return this.name && !this.disabled &&
                (this.checked || /select|textarea/i.test(this.nodeName) ||
                    /text|hidden|password|search/i.test(this.type));
        })
        .map(function (i, elem) {
            var val = jQuery(this).val();
            return val == null ?
                null : { name: elem.name, value: val }
        }).get();
     $(form).find("input:checkbox")
        .filter(function () {
            return this.name;
        })
        .each(function(index, elem) {
            arr = $.grep(arr, function(item, index){
                return elem.name != item.name;
            });
            arr.push({ name: elem.name, value: (elem.checked ? "true" : "false") });
        });
    return processNameValues(json, arr, true, false);
}
hahmed commented 12 years ago

+1 @michael-lang - this is exactly the issue I am facing with .net, I am also looking at a way to igonore hidden fields

michael-lang commented 12 years ago

ha25gmail, to ignore hidden fields, take my code and just remove the 'hidden' portion in the test function call.

    .filter(function () {
        return this.name && !this.disabled &&
            (this.checked || /select|textarea/i.test(this.nodeName) ||
                /text|password|search/i.test(this.type));
    })

You can find my current experimental code here: http://jsfiddle.net/mjlang/h33DV/8/

This jsFiddle does not 'run' because I haven't done the faking of the ajax calls using the jsFiddle convention yet, but the javascript code does work in my real project.