2012-07-05 89 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