web-dev-qa-db-ja.com

jqueryシリアライズと$ .post

JQueryの$ .postメソッドを使用して、フォームから大量のデータを送信しようとしています。最初にserialize()関数を使用して、すべてのフォームデータを1つの長い文字列にしてから、サーバーサイドで分解します。奇妙なことに、$。postを使用して送信しようとすると、GETを使用して送信しているかのように、serialize()の結果がURLに追加されます。なぜこれが起こっているのですか?

ここにjqueryがあります:

$("#addShowFormSubmit").click(function(){
  var perfTimes = $("#addShowForm").serialize();
  $.post("includes/add_show.php", {name: $("#showTitle").val(), results: perfTimes }, function(data) {
    $("#addShowSuccess").empty().slideDown("slow").append(data);
  });
});  

ここにphpがあります:

$show = $_POST['name'];
$results = $_POST['results'];
$perfs = explode("&", $results);
foreach($perfs as $perf) {
    $perf_key_values = explode("=", $perf);
    $key = urldecode($perf_key_values[0]);
    $values = urldecode($perf_key_values[1]);
}
echo $key, $values;  
22
musoNic80

_<button>_要素を使用してシリアライズとajaxをアクティブ化し、その_<button>_要素がform要素内にある場合、buttonは自動的にフォームとして機能しますjQueryで他にどの.click割り当てを指定しても、送信されます。

type = 'submit'

_<button></button>_と_<button type='submit'></button>_は同じものです。 _<form>_要素内に配置されている場合、フォームを送信します。

type = 'button'

_<button type='button'></button>_は異なります。これは通常のボタンにすぎず、フォームを送信しません(JavaScriptを使用して意図的にフォームを送信しない限り)。

form要素にaction属性が指定されていない場合、この送信はデータを同じページに送り返すだけです。つまり、ajaxでGETを使用した場合と同じように、URLにシリアル化されたデータが表示され、ページが更新されることになります。

可能な解決策

1-_<button>_タイプbuttonを作成します。上で説明したように、これはボタンがフォームを送信するのを防ぎます。

前:

_<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
    <button id='mySubmitButton'>Submit</button>
</form>
_

後:

_<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
<button type='button' id='mySubmitButton'>Submit</button>
</form>
_

2-_<button>_要素を_<form>_要素の外に移動します。これにより、ボタンがフォームを送信できなくなります。

前:

_<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
    <button id='mySubmitButton'>Submit</button>
</form>
_

後:

_<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
</form>
<button id='mySubmitButton'>Submit</button>
_

3-preventDefault()をボタンクリックハンドラーに追加して、フォームが送信されないようにします(デフォルトのアクションです)。

_$("#addShowFormSubmit").click(function(event){
  event.preventDefault();
  var perfTimes = $("#addShowForm").serialize();
  $.post("includes/add_show.php", {name: $("#showTitle").val(), results: perfTimes },      function(data) {
    $("#addShowSuccess").empty().slideDown("slow").append(data);
  });
});
_

明らかに、すべてのコードを確認せずに、これがあなたの問題の原因であるかどうかはわかりませんが、あなたが説明している動作を見た唯一の理由は、送信ボタンがタイプが指定されていない_<button>_であったためです。

18
Jake Wilson

serialize()の代わりにserializeArray()を使用してみてください。 serialize()はURLエンコードされたクエリ文字列を生成しますが、serializeArray()はJSONデータ構造を生成します。

7
Franz

データがURLに追加されていると思われるのはなぜですか?

とにかく、フォームデータ自体でフォームの値を渡す方が理にかなっているのではないでしょうか。 「分解」ステップをスキップできます。

$("#addShowFormSubmit")
  .click(function() { 
      var perfTimes = $("#addShowForm").serialize(); 
      $.post("includes/add_show.php", 
         $.param({name: $("#showTitle").val()}) + "&" + perfTimes, 
         function(data) {...}); 
  });
3

だからこれは少しややこしいかもしれませんが、毎回たくさんの修正をするのに飽きたので、これを行うのに役立つ関数を作りました。 serializeArrayは、PhPに再構築させたいのが連想配列だけだった場合に、オブジェクトのコレクションを提供するため、一種の煩わしいものです。以下の関数は、シリアル化された配列を処理し、値が存在する場合にのみ、適切なプロパティを持つ新しいオブジェクトを構築します。

まず、関数(問題のフォームのIDを受け取ります):

_function wrapFormValues(form) { 
    form = "#" + form.attr("id") + " :input";
    form = $(form).serializeArray();
    var dataArray = new Object();

    for( index in form)
    {   
        if(form[index].value)   {
            dataArray[form[index].name] = form[index].value;    
        }
    }       

    return dataArray; 
}
_

投稿を作成するときも、通常はオブジェクトを使用します。通常、フォームデータの前に他の2つまたは3つの値をタグ付けし、インラインで定義するよりもきれいに見えるため、最後の手順は次のようになります。

_var payload = new Object(); 
//stringify requires json2.js from http://www.json.org/js.html
payload.data = JSON.stringify(data);

$.post("page.php", payload,  
    function(reply) {
        //deal with reply.
    });
_

サーバー側で行う必要があるのは$payload = json_decode($_POST['data'], true)だけで、キーはフォームフィールドの名前である連想配列です。

完全な免責事項ですが、複数選択はおそらくここでは機能せず、リストの最後にある値しか取得できないでしょう。これも私のプロジェクトに合わせて特別に作成されているので、自分に合うように微調整することをお勧めします。たとえば、サーバーからのすべての返信にjsonを使用しています。

2
Vassi

この問題の考えられるもう1つの理由:何らかの送信アクションが割り当てられていないフォームがある場合、フォームへの入力中に「Enter」キーを押すと、フォームは現在のURLに送信されるため、 GET ajaxトランザクションを使用しているかのように、シリアル化されたデータがURLに表示されることを確認してください。この問題の簡単な解決策は、Enterキーを押したときにフォームが送信されないようにすることです。

//Prevent Form Submission when Pressing Enter
$("form").bind("keypress", function(e) {
if (e.keyCode == 13)
    return false;
});
0
Jake Wilson

この構文を試してください。これを使用してフォームとPOSTをWCFサービスへのajax呼び出しでシリアル化します。また、この方法でオブジェクトを構築する代わりに、これを単一のJSONオブジェクトに送り返すこともできます。これを試してください:

var serializedForm = serializedForm = $("#addShowForm").serializeArray();

$.post("includes/add_show.php", 
    {
        "myObjectName": ("#showTitle").val(), results: perfTimes 
    }, function(data) 
        {
            $("#addShowSuccess").empty()
            .slideDown("slow")
            .append(JSON.stringify(serializedForm)); 
        });
0
Zacho

PHP側では、 parse_str を調べたい場合があります。 2番目のオプションパラメータを使用する場合は、そのURL文字列を変数または配列に解析します。

0
Chris Rasco