1

Is there a way to turn a form into a complex JavaScript object based some structured form?

Now, I have no idea if this should be done in a better way, but basically I want something like this:

<form>
   <input name="Foo" value="1" />
   <input name="Parent.Child1" value="1" />
   <input name="Parent.Child2" value="2" />
</form>

and I want this in JavaScript:

var form = GetForm();
var obj = ConvertFormToComplexObject(form);

//
// Followings should be true
// 
// obj.Foo == 1;
// obj.Parent != null
// obj.Parent.Child1 == 1;
// obj.Parent.Child2 == 2;
// 

Any suggestions?

Thanks,

2
  • 1
    To what end? This just seems like a variation on basic DOM scripting; why not just learn to use normal DOM scripting? Commented Aug 5, 2010 at 19:56
  • Hm.. basically, I have a form with dynamic form elements. The user can add a list of "objects" where each "object" each contains an integer and a string. I can keep the form flat by having a naming convention like name="1_Integer", or name="2_String", but I will have to write a parser. If I build the JavaScript object correctly. I can use Json to serialize it and let Json take care of the complexity. Commented Aug 5, 2010 at 20:41

5 Answers 5

2

I wrote a plugin to do just that. Hope it will help someone out there. Let me know if you find any bugs.

Here's the code for serializeObject.js:

$.fn.serializeObject = function() {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {

        var arrayIndex = function(name) {
            //note: 2d array not handled

            var startIndex = name.indexOf('[');
            var endIndex = name.indexOf(']');

            if (startIndex == -1 || endIndex == -1 || endIndex != name.length - 1)
                return null;

            return name.substr(startIndex + 1, endIndex - startIndex - 1);
        }

        var trimArrayIndex = function(name) {
            var startIndex = name.indexOf('[');
            return name.substr(0, startIndex);
        }

        var createObject = function(obj, className, value) {
            if (className.length == 0)
                return;

            var classNames = className.split(".");

            if (classNames.length == 1) {

                if (obj[classNames[0]] == null) {
                    obj[classNames[0]] = value;
                }
                else if (obj[classNames[0]] instanceof Array) {
                    obj[classNames[0]].push(value);
                }
                else {
                    var temp = obj[classNames[0]];

                    obj[classNames[0]] = new Array();
                    obj[classNames[0]].push(temp);
                    obj[classNames[0]].push(value);
                }

                return;
            }

            var index = arrayIndex(classNames[0]);
            var isArray = index != null;

            if (!isArray) {
                if (obj[classNames[0]] == null) {
                    obj[classNames[0]] = new Object();
                }

                createObject(obj[classNames[0]], className.substr(classNames[0].length + 1), value);
            }
            else {
                var aryName = trimArrayIndex(classNames[0]);

                if (obj[aryName] == null) {
                    obj[aryName] = new Array();
                }
                else if (!obj[aryName] instanceof Array) {
                    throw "unable to serialize " + aryName + " as an array";
                }

                var ary = obj[aryName];
                var nextObj;

                if (ary[parseInt(index)] == null) {
                    ary[parseInt(index)] = new Object();
                }

                nextObj = ary[parseInt(index)];

                createObject(nextObj, className.substr(classNames[0].length + 1), value);
            }
        }

        createObject(o, this.name, this.value || '');
    });
    return o;
};

$.fn.replaceStarWithIndex = function() {
    var a = this.serializeArray();
    var form = this;


    var arrayIndex = function(name) {
        var startIndex = name.indexOf('[');
        var endIndex = name.indexOf(']');

        if (startIndex == -1 || endIndex == -1) {
            return null;
        }

        return name.substr(startIndex + 1, endIndex - startIndex - 1);
    }

    var trimArrayIndex = function(name) {
        var startIndex = name.indexOf('[');
        return name.substr(0, startIndex);
    }

    for (var key in a) {
        var index = arrayIndex(a[key].name);

        if (index == null || index != "*") {
            continue;
        }

        var count = 0;
        var trimName = trimArrayIndex(a[key].name);

        while (true) {
            var elementName = a[key].name.replace('*', count);
            var element = form[0][elementName];

            if (element == null) {
                $(form[0][a[key].name]).first().attr('name', elementName);
                break;
            }
            count++;
        }
    }
}   

Here's the test:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Test</title>
    <link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen" />

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" ></script>
    <script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js" ></script>
    <script type="text/javascript" src="serializeObject.js" ></script>
</head>

<body>

<h1 id="qunit-header">Test serializeObject</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>

<!--Test Form -->

<form id="form1" style="display:none;">
    <input type="text" name="Parent.Child1" value="child1"/>

    <input type="text" name="Parent.Child2" value="child2a"/>
    <input type="text" name="Parent.Child2" value="child2b"/>

    <input type="text" name="Parent.Child3" value="3"/>
    <input type="text" name="Parent.Child3" value="2"/>
    <input type="text" name="Parent.Child3" value="1"/>

    <input type="text" name="Parent.Child4[0].Child1" value="11" />
    <input type="text" name="Parent.Child4[0].Child2" value="aa" />

    <input type="text" name="Parent.Child4[1].Child1" value="22" />
    <input type="text" name="Parent.Child4[1].Child2" value="bb" />



</form>   

<form id="form2" style="display:none;">
    <input type="text" name="Child1[0].Child1" value="0" />
    <input type="text" name="Child1[*].Child1" value="1" />
    <input type="text" name="Child1[*].Child1" value="2" />

    <input type="text" name="Child2[2]" value="2" />
    <input type="text" name="Child2[*]" value="0" />
    <input type="text" name="Child2[*]" value="1" />
</form> 

<script type="text/javascript">
    $(document).ready(function() {
        var obj = $('#form1').serializeObject();

        test("Parent should exist", function() {
            equals(true, obj.Parent != null);
        });

        test("Child1 should exist within parent", function() {
            equals(true, obj.Parent.Child1 != null);
        });

        test("Should create array for items with same name", function() {
            equals("child2a", obj.Parent.Child2[0]);
            equals("child2b", obj.Parent.Child2[1]);
            equals("3", obj.Parent.Child3[0]);
            equals("2", obj.Parent.Child3[1]);
            equals("1", obj.Parent.Child3[2]);
        });


        test("Should allow array of objects", function() {
            equals("11", obj.Parent.Child4[0].Child1);
            equals("aa", obj.Parent.Child4[0].Child2);
            equals("22", obj.Parent.Child4[1].Child1);
            equals("bb", obj.Parent.Child4[1].Child2);
        });

        $('#form2').replaceStarWithIndex();

        test("Should replace * with index", function() {
            equals("0", $('#form2 input[name="Child1[0].Child1"]').val());
            equals("1", $('#form2 input[name="Child1[1].Child1"]').val());
            equals("2", $('#form2 input[name="Child1[2].Child1"]').val());

            equals("0", $('#form2 input[name="Child2[0]"]').val());
            equals("1", $('#form2 input[name="Child2[1]"]').val());
            equals("2", $('#form2 input[name="Child2[2]"]').val());
        });

    });
</script>

</body>
</html>
Sign up to request clarification or add additional context in comments.

Comments

0

i guess you are asking for document.forms[0]

something like:

var form = document.forms[0]; //or can be document.getElementByName...

then you can access its values as you are trying: form.Foo = 1

you do not need to convert it to complex object DOM itself is sufficent for that

Comments

0
var form = document.forms[0];

return a HTML Element Object,you can use

form.Foo

get a HTML Element too

but if you want to get value,must use:

form.Foo.value

or

form['Parent.Child1'].value;

you can see this DEMO

P.S. i think ConvertFormToComplexObject() method is not good.you don't need to create it.

1 Comment

Thanks Zenofo, but I want "Parent" to be an object so I can have the option to serialize it into Json if I wanted to. In your case, form.Parent is null or form.Parent.Child1 gives an error
0

Its a names[0]very basic version but it should give you a basic understanding on how this work.

$(function(){
    var elements = document.forms[0].elements,
        foo = {};
    for(var i=0; i<elements.length; i++) {
        var element = elements[i];
        var names = element.name.split('.');
        if(names.length >1) {
            foo[names[0]] = foo[names[0]] || {};
            foo[names[0]][names[1]] = element.value;
        } else {
         foo[names[0]] = element.value;
        }

    }
    console.log(foo)
});​

Comments

0

Numerous Javascript libraries have this functionality. I suggest you use their implementation, or at least see how they've done it.

Prototype: http://www.prototypejs.org/api/form/serialize

Usage: $('id-of-form').serialize(true)

1 Comment

I have looked at the jQuery one, but it doesn't do the "structured" object serialization. In fact, this it doesn't even serialize it into an object. The closest I got it this: stackoverflow.com/questions/1184624/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.