Closed lookfirst closed 13 years ago
I've written this and will be contributing it back soon. Its done with CoffeeScript and JQuery. It works with all of the examples for this project except the Ruby one. I don't care about Ruby, so someone else can figure out that logic. ;-)
Check out develop branch (9d7ca0afd4029940e7e091b62b9775eb8e1cf4a2)
Here is mine (in coffeescript + jquery). I went a different direction...
flattenData = (json, elem=[], frag) ->
for key, value of json
if $.type(value) == "object"
complete = if !frag then key else "#{frag}.#{key}"
flattenData(value, elem, complete)
else if $.type(value) == "array"
if value[0] && $.type(value[0]) == "object"
cnt = 0
for valObj in value
for kval, vval of valObj
elem.push({key: "#{frag}.#{key}[#{cnt}].#{kval}", value: vval})
cnt++
else
complete = if !frag then "#{key}[]" else "#{frag}.#{key}[]"
flattenData(value, elem, complete)
else
# necessary for person.favFood test
if $.type(json) == "array"
complete = if !frag then key else "#{frag}"
else
complete = if !frag then key else "#{frag}.#{key}"
elem.push({key: complete, value: value})
return elem
json2Form = (@data, @form) ->
flattened = flattenData(@data)
for flat in flattened
@key = flat.key
@value = flat.value
@flds = $('[name^="' + @key + '"]', @form)
for fld in @flds
@jfld = $(fld) # convert to jquery
switch fld.type
when "textarea", "hidden", "text"
@jfld.val(@value).change()
when "select-one", "select-multiple"
$('select[name="' + fld.name + '"] option', @form).each (i, e) =>
e = $(e)
if e.val() == "#{@value}"
e.attr('selected', true)
else
e.removeAttr('selected')
e.change()
when "checkbox", "radio"
if @jfld.val() == "#{@value}"
@jfld.attr('checked', true)
else
@jfld.removeAttr('checked')
@jfld.change()
Most complex thing in my implementation of deserialization is arrays. Array index in field name should be unique, but it's not necessary to have index 0 'zero' at first element, or to have consecutive indexes (order of appearance in document used instead). This is useful for dynamic form elements creation, because we have to increment index and insert form fields in proper place to add item, and just remove form fields to remove item.
So if we have this form:
<form>
<input type="text" name="array[10000].name" value="val1">
<input type="text" name="array[5].name" value="val2">
</form>
form2js will return this data:
{
"array" : [
{ "name" : "val1" },
{ "name" : "val2" }
]
}
and it seems like your implementation will not populate original form with it, but sure it's enough in some cases.
Ah, I didn't realize that was part of the criteria. I'll gladly switch to your code! Thanks for creating this great tool.
That said, I'd appreciate it if you'd write it in coffeescript/jquery. Much easier to read!
i'm trying to use js2form. i'm not sure what i need to put in as the first argument for the function: rootNode.
it would be great if you guys could give me an example of how to use it. thank you.
to use this am i supposed to have my form already set up so that it conforms to the JS object? i guess i expected it to make my webpage for me, via 300 lines of magic javascript :)
Correct, it doesn't create a form =)
I'm using form2js and it's working great for me. now i'm trying to take the data i get out of form2js and put it back in the same form via js2form. i'm not really sure what object to pass into it as the root node. i guessed that it would be a jQuery object. code below
var rootNode = $("#testForm");
js2form(rootNode, data, '.', true);
I see that getFields() needs rootNode to have a firstchild object. the object i get from jQuery doesn't have that field. what object should i use?
i found out how to do this document.getElementById('testForm');
via the example html code
i made a js2form repo. at first it was based off of your code, but then i just rewrote it all after i found that underscore .toArray() and jQuery did almost all of the work for me.
i don't think it's as complete as yours, but it's much smaller and easier to extend, which i will be doing soon.
max: Thanks for doing this. I noticed this issue in the code for js2form, you are missing this line:
rootNode = typeof rootNode == 'string' ? document.getElementById(rootNode) : rootNode;
This little library is great. It is exactly what I'm looking for.
That said, I'd love the opposite direction as well.
I'd love to be able to take a chunk of json and have it apply to all of the input/textarea's on a page.
The usecase for this is handling of the 'cancel' button. I'd love to just reset everything to its prior values.
Thanks,
jon