2012-07-05 50 views
134

我想对Backbone.js模型中的表单进行一些预服务器验证。为此,我需要将来自表单的用户输入转化为可用数据。 我找到了三种方法来做到这一点:将表单数据序列化为JSON

  1. var input = $("#inputId").val();
  2. var input = $("form.login").serialize();
  3. var input = $("form.login").serializeArray();

不幸的是,没有一个提供我需要一个良好的reabable和显影JSON对象。我已经浏览了堆栈 溢出的几个问题,但是我发现只有一些额外的库。

是不是Underscore.js,目前jQuery还是Backbone.js提供了一个辅助方法?

我无法想象没有这样的功能请求。

HTML

<form class="login"> 
    <label for="_user_name">username:</label> 
    <input type="text" id="_user_name" name="user[name]" value="dev.pus" /> 
    <label for="_user_pass">password:</label> 
    <input type="password" id="_user_pass" name="user[pass]" value="1234" /> 
    <button type="submit">login</button> 
</form> 

的JavaScript

var formData = $("form.login").serializeObject(); 
console.log(formData); 

输出

{ 
    "name": "dev.pus", 
    "pass": "1234" 
} 

Backbone.js的模型

var user = new User(formData); 
user.save(); 
+1

jQuery有用于JSON插件:http://code.google.com/p/jquery- json /,它不包含辅助方法。 – nilgun

+4

'.serializeArray()'有什么问题? – xdazz

+2

我需要它的形式,我只是想知道,三个框架不提供表格映射... –

回答

99

你可以这样做:

function onSubmit(form){ 
 
    var data = JSON.stringify($(form).serializeArray()); // <----------- 
 

 
    console.log(data); 
 
    return false; //don't submit 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<form onsubmit='return onSubmit(this)'> 
 
    <input name='user' placeholder='user'><br> 
 
    <input name='password' type='password' placeholder='password'><br> 
 
    <button type='submit'>Try</button> 
 
</form>

看到这一点:http://www.json.org/js.html

+27

嗨,不是。我得到类似于{“name”:“user [name]”value:“dev.pus”}但我想{“name”:“dev.pus”,“password”:“1234”}等。 –

+2

@ dev.pus:您可能需要在[{“name”:“username”,“value”:“foo”}]格式中处理它。否则,您无法处理具有相同名称的多个元素。 –

+9

如果您没有多个具有相同名称的元素,则可以轻松地将表单数据转换为JSON字符串,如下所示:var myjson = {}; $ .each(allFormTags,function(){myjson [this.name] = this.value;}); – TechyTimo

112

下面是这个用例的功能:

function getFormData($form){ 
    var unindexed_array = $form.serializeArray(); 
    var indexed_array = {}; 

    $.map(unindexed_array, function(n, i){ 
     indexed_array[n['name']] = n['value']; 
    }); 

    return indexed_array; 
} 

用法:

var $form = $("#form_data"); 
var data = getFormData($form); 
+0

它越来越近了。我已经更新了启动线程,我认为它应该看起来像... –

+2

代码覆盖具有相同名称的键。你应该检查indexed_array [n ['name']]是否已经存在,如果它将其转换为数组并在那里添加n ['value']。当然,你也需要检查indexed_array [n ['name']]是否已经是一个数组。 – Strix

+12

名称应该总是唯一的(单选按钮,只能有一个值!),如果不是 - 只有重复名称的字段的最后一次出现与请求一起发送。如果你想创建多级数组结构,你必须检测方括号,并从该信息构建多维数组。提示:将第一部分字段名称用圆括号括起来。 'somefield [2] => [somefield] [2]'并且使用eval来赋值'eval('you_array_varialbe'+ bracketed_field_name +'= \''+ n ['value'] +'''')' –

-1

找到一个可能的帮手:

https://github.com/theironcook/Backbone.ModelBinder

并为人们谁不想与形式取得联系,在所有: https://github.com/powmedia/backbone-forms

我会仔细看看第一个链接,并给出一些反馈:)

+0

查看http://stackoverflow.com/questions/1184624/convert-form-data-to-js-object-with-jquery: var data = {}; ()。(“。form-selector”)。serializeArray()。map(function(x){data [x.name] = x.value;}); – GKislin

5

如果您使用JSON发送表单,则必须删除发送字符串中的[]。你可以做到这一点与jQuery函数serializeObject():

var frm = $(document.myform); 
var data = JSON.stringify(frm.serializeObject()); 

$.fn.serializeObject = function() { 
    var o = {}; 
    // var a = this.serializeArray(); 
    $(this).find('input[type="hidden"], input[type="text"], input[type="password"], input[type="checkbox"]:checked, input[type="radio"]:checked, select').each(function() { 
     if ($(this).attr('type') == 'hidden') { //if checkbox is checked do not take the hidden field 
      var $parent = $(this).parent(); 
      var $chb = $parent.find('input[type="checkbox"][name="' + this.name.replace(/\[/g, '\[').replace(/\]/g, '\]') + '"]'); 
      if ($chb != null) { 
       if ($chb.prop('checked')) return; 
      } 
     } 
     if (this.name === null || this.name === undefined || this.name === '') 
      return; 
     var elemValue = null; 
     if ($(this).is('select')) 
      elemValue = $(this).find('option:selected').val(); 
     else elemValue = this.value; 
     if (o[this.name] !== undefined) { 
      if (!o[this.name].push) { 
       o[this.name] = [o[this.name]]; 
      } 
      o[this.name].push(elemValue || ''); 
     } else { 
      o[this.name] = elemValue || ''; 
     } 
    }); 
    return o; 
} 
17

我知道这不符合辅助函数的要求,但我这样做的方法是使用jQuery的$。每()方法

var loginForm = $('.login').serializeArray(); 
var loginFormObject = {}; 
$.each(loginForm, 
    function(i, v) { 
     loginFormObject[v.name] = v.value; 
    }); 

然后,我可以将loginFormObject传递给我的后端,或者您可以创建一个userobject并将其保存到主干中。

+0

这很好,很简单,而且对我现在的需求来说似乎是完美的。干得好! –

+0

我试图用它来解决其他问题,但我在这里发现了一个问题。在通过ASP.NET MVC(Razor风格视图)完成的网站上,代码生成可见复选框输入和隐藏输入。使用你的代码,'loginForm'包含两个输入(如果复选框被选中,'false'只有其他的输入),然后'loginFormObject'获得第二个输入,总是'false'。这里的解决方案:在'each'的子函数中,在'{':'if(formObject [v.name]!=“true”)后添加以下行。这将保留“真实”。 – MilConDoin

4

以下是我使用的这种情况作为一个模块(在我formhelper.js):

define(function(){ 
    FormHelper = {}; 

    FormHelper.parseForm = function($form){ 
     var serialized = $form.serializeArray(); 
     var s = ''; 
     var data = {}; 
     for(s in serialized){ 
      data[serialized[s]['name']] = serialized[s]['value'] 
     } 
     return JSON.stringify(data); 
    } 

    return FormHelper; 
}); 

它那种很烂,我似乎无法找到另一种方式做我想做的做。

这不返回该JSON对我来说:

{"first_name":"John","last_name":"Smith","age":"30"} 
9

如果你不关心使用相同的名称重复的表单元素,那么你可以做:

var data = $("form.login").serializeArray(); 
var formData = _.object(_.pluck(data, 'name'), _.pluck(data, 'value')); 

我使用Underscore.js这里。

5

为了解决同样的问题(无需进入复杂的插件和库进行验证),我创建了jQuery.serializeJSON,它改进了serializeArray以支持任何种类的嵌套对象。

这个插件非常流行,但在另一个项目中我使用的是Backbone.js,我想在Backbone.js模型中编写验证逻辑。然后我创建了Backbone.Formwell,它允许您直接在表单中显示验证方法返回的错误。

38

下面的代码应该可以帮到你。 :)

//The function is based on http://css-tricks.com/snippets/jquery/serialize-form-to-json/ 
<script src="//code.jquery.com/jquery-2.1.0.min.js"></script> 

<script> 
    $.fn.serializeObject = function() { 
     var o = {}; 
     var a = this.serializeArray(); 
     $.each(a, function() { 
      if (o[this.name]) { 
       if (!o[this.name].push) { 
        o[this.name] = [o[this.name]]; 
       } 
       o[this.name].push(this.value || ''); 
      } else { 
       o[this.name] = this.value || ''; 
      } 
     }); 
     return o; 
    }; 

    $(function() { 
     $('form.login').on('submit', function(e) { 
      e.preventDefault(); 

      var formData = $(this).serializeObject(); 
      console.log(formData); 
      $('.datahere').html(formData); 
     }); 
    }); 
</script> 
2

使用jQuery和避免serializeArray,下面的代码序列化和发送JSON格式的表单数据:

$("#commentsForm").submit(function(event){ 
    var formJqObj = $("#commentsForm"); 
    var formDataObj = {}; 
    (function(){ 
     formJqObj.find(":input").not("[type='submit']").not("[type='reset']").each(function(){ 
      var thisInput = $(this); 
      formDataObj[thisInput.attr("name")] = thisInput.val(); 
     }); 
    })(); 
    $.ajax({ 
     type: "POST", 
     url: YOUR_URL_HERE, 
     data: JSON.stringify(formDataObj), 
     contentType: "application/json" 
    }) 
    .done(function(data, textStatus, jqXHR){ 
     console.log("Ajax completed: " + data); 
    }) 
    .fail(function(jqXHR, textStatus, errorThrown){ 
     console.log("Ajax problem: " + textStatus + ". " + errorThrown); 
    }); 
    event.preventDefault(); 
}); 
1

我的贡献:

function serializeToJson(serializer){ 
    var _string = '{'; 
    for(var ix in serializer) 
    { 
     var row = serializer[ix]; 
     _string += '"' + row.name + '":"' + row.value + '",'; 
    } 
    var end =_string.length - 1; 
    _string = _string.substr(0, end); 
    _string += '}'; 
    console.log('_string: ', _string); 
    return JSON.parse(_string); 
} 

var params = $('#frmPreguntas input').serializeArray(); 
params = serializeToJson(params); 
37

用途:

var config = {}; 
jQuery(form).serializeArray().map(function(item) { 
    if (config[item.name]) { 
     if (typeof(config[item.name]) === "string") { 
      config[item.name] = [config[item.name]]; 
     } 
     config[item.name].push(item.value); 
    } else { 
     config[item.name] = item.value; 
    } 
}); 
+1

这不是一个通用的解决方案;一个表单可以有多个相同的键的值。这个函数只会保留最后一个值。 – pimlottc

+1

确实,改编了答案 - 谢谢 – Maertz

+0

最后一个值是标准方法,对覆盖以前的值非常有用。 – ppumkin

7

I cou ldn't发现,将解决这个问题一个答案:

[{name:"Vehicle.Make", value: "Honda"}, {name:"Vehicle.VIN", value: "123"}] 

这就要求该对象:

{Vehicle: {Make: "Honda", "VIN": "123"}} 

所以我不得不写我自己的串行器将解决这个问题:

function(formArray){ 
     var obj = {}; 
     $.each(formArray, function(i, pair){ 
      var cObj = obj, pObj, cpName; 
      $.each(pair.name.split("."), function(i, pName){ 
       pObj = cObj; 
       cpName = pName; 
       cObj = cObj[pName] ? cObj[pName] : (cObj[pName] = {}); 
      }); 
      pObj[cpName] = pair.value; 
     }); 
     return obj; 
    } 

也许它会帮助别人。

+0

不错。这对我有用。 –

+0

我正在寻求这样一个答案,你让我的一天!谢谢soooooo多! – AlexB

0

嗯,这里是因为它方便的插件:https://github.com/macek/jquery-serialize-object

它的问题是:

展望未来,核心系列化的顶部,.serializeObject将支持布尔和数值正确serializaton ,导致两种情况的有效类型。

期待这些在> = 2.1.0

5

使用Underscore.js

function serializeForm($form){ 
    return _.object(_.map($form.serializeArray(), function(item){return [item.name, item.value]; })); 
} 
+1

这不是一个通用的解决方案;一个表单可以有多个相同的键的值。这个函数只会保留最后一个值。 – pimlottc