##やりたい事
formの値を、jsonに変換して、postしたい。
そして、action先に遷移したい。
ちなみに、
「出来るだけフロント側で対応してほしい。(他のデータは送らずJSONだけ送ってほしい)」
と言われているため、JSON以外のformデータも全て送ってサーバ側で処理...というのはNGです。
(2016/11/22 追記)
postするのは$.ajax()でなく、$.post()でもOKです。
(2016/11/22 追記)
調べたら、
submit:画面は遷移するが、JSONは送れない?
$.ajax/$.post:画面は遷移しないが、JSONは送れる?
やりたい事は「画面は遷移したい。JSONも送りたい。」なので、どうすれば...???
##やった事
<!----- 前略 -----> <form action="hoge" method="post"> <!----- 中略 -----> </form> <!----- 後略 -----> <script> $('form').submit(function(){ // form値をJSONに変換 var data = $('form').serializeArray(); // jQueryを使ってpost $.ajax({ type: $('form').attr('method'), url: $('form').attr('action'), dataType: 'json', contentType: 'application/json', scriptCharset: 'utf-8', data: JSON.stringify(data) }); // 本来のsubmitイベントはしない return false; // 上記のままだと画面 hoge に遷移しない。 // hogeに遷移したい。 }); </script>
##環境
Ruby on Rails
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
状況がよくわからないのですが
ajaxでpostしたあとpostしたら二重投稿になりませんか?
むしろ同じデータをおくるのであればajaxでおくらずにpostするだけでよいのでは?
仮にajaxでpostしたあとにページの遷移をするだけなら
location.hrefでデータを送らない遷移ではいけないのでしょうか?
追記
とりあえずajaxの部分はこうしてください
javascript
1<script> 2$(function(){ 3 $('form').on('submit',function(){ 4 var data = {}; 5 $(this).find('input[name]').each(function(){ 6 data[$(this).prop('name')]=$(this).val(); 7 }); 8 console.log(JSON.stringify(data)); 9 $.ajax({ 10 type: $('form').attr('method'), 11 url: $('form').attr('action'), 12 dataType: 'text', 13 data: data, 14 success:function(d){ 15 console.log(d); 16 }, 17 }); 18 return false; 19 }); 20}); 21 22</script> 23<form method="post" action="xxx.php"> 24<input type="text" name="aaa" value="123"> 25<input type="hidden" name="bbb" value="xyz"> 26<input type="submit" value="go"> 27</form> 28 29
投稿2016/11/22 03:31
編集2016/11/22 07:07総合スコア117009
0
input要素に追加するとか。(他の要素も一緒にPOSTされますが、受け取り側で無視すればよいです)
JavaScript
1$( 'form' ).submit( function() { 2 // form値をJSONに変換 3 var data = JSON.stringify( $( 'form' ).serializeArray() ); 4 $( 'form' ).html( '<input type="hidden" name="json" value="' + data + '">' ); 5} ); // 未テスト
追記:
じゃあフォームを追加すればよいのでは?
JavaScript
1$( 'form' ).submit( function() { 2 // form値をJSONに変換 3 var data = JSON.stringify( $( 'form' ).serializeArray() ); 4 var action = $( 'form' ).attr( 'action' ); 5 $( 'form' ).after( '<form id="jsonpost" action="' + action + '"><input type="hidden" name="json" value="' + data + '"></form>' ); 6 $( 'form#jsonpost' ).submit(); 7 return false; 8} ); // 未テスト
投稿2016/11/22 03:00
編集2016/11/22 03:18総合スコア69612
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/22 03:14 編集
2016/11/22 03:14
2016/11/22 03:14
2016/11/22 05:56
2016/11/22 06:20
2016/11/22 06:46
2016/11/22 06:47
2016/11/22 08:32
2016/11/28 00:58
2016/11/28 05:44
0
ベストアンサー
サーバー側がContent-Type:application/json
のデータのPOSTしか受け付けず、かつ結果をContent-Type:text/html
で返してくる、ということですね。そしてそのHTMLを表示したいと。
この場合、HTMLのformではJSONはPOSTできませんので、実現不可能です。よってAjaxなり、他の方法でJSONをPOSTするしかないのですが、その場合は「画面遷移」が不可能です。
なので私が思いつく案としては受け取ったHTMLで現在のドキュメントの内容を書き換えて「遷移に見せかける」くらいしかありませんが、以下のサンプルのような感じではどうでしょうか。
html
1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <title>a</title> 6 <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> 7</head> 8<body> 9 <form action="b.html"> 10 </form> 11 <button id="a">submit</button> 12 <script> 13 var data = {"message": "hello"}; 14 var action = $("form").attr("action"); 15 var forwarded = false; 16 $("#a").on("click", function() { 17 $.ajax({ 18 type: "POST", 19 url: action, 20 dataType: "html", 21 contentType: "application/json", 22 data: JSON.stringify(data), 23 success: function(res) { 24 // レスポンスからDOMを構築してscriptタグだけ復元可能なようにしておく 25 newHtml = new DOMParser().parseFromString(res, "text/html"); 26 var scriptElements = Array.prototype.map.call( 27 newHtml.getElementsByTagName("script"), function(elem) { 28 return elem; 29 } 30 ); 31 var scriptParents = []; 32 var scriptNexts = scriptElements.map(function(elem) { 33 scriptParents.push(elem.parentNode); 34 for(;elem.nextSibling !== null && elem.nextSibling.tagName === "script"; 35 elem = elem.nextSibling) {} 36 return elem.nextSibling; 37 }); 38 var i = 0; 39 for(i = 0; i < scriptParents.length; i++) { 40 scriptParents[i].removeChild(scriptElements[i]); 41 } 42 43 // 現在のドキュメントを空(<html>のみ)にする 44 while(document.documentElement.firstChild) { 45 document.documentElement.removeChild(document.documentElement.firstChild); 46 } 47 // レスポンスのDOMから現在のドキュメントに要素を移動させる 48 while(newHtml.documentElement.firstChild) { 49 document.documentElement.appendChild( 50 newHtml.documentElement.removeChild(newHtml.documentElement.firstChild)); 51 } 52 // scriptの復元 53 var loaded = Promise.resolve(); 54 for(i = 0; i < scriptParents.length; i++) { 55 (function(i) { 56 loaded = loaded.then(function() { 57 return new Promise(function(resolve) { 58 var script = document.createElement("script"); 59 for(var j = 0; j < scriptElements[i].attributes.length; j++) { 60 var attr = scriptElements[i].attributes.item(j); 61 script.setAttribute(attr.name, attr.value); 62 if(attr.name === "src") { 63 // ファイルを読み込んでいる場合は以降のコードは読み込み終わってからでないといけない 64 script.onload = function() { resolve(); }; 65 } 66 } 67 scriptParents[i].insertBefore(script, scriptNexts[i]); 68 script.textContent = scriptElements[i].textContent; 69 if(!script.onload) { resolve(); } 70 }); 71 }); 72 })(i); 73 } 74 75 // 「戻る」対応 76 if(!forwarded) { 77 history.pushState(null, null, action); 78 } 79 window.onpopstate = function(){ 80 location.reload(); 81 }; 82 }, 83 }); 84 }); 85 // 「進む」対応 86 window.onpopstate = function(){ 87 if(location.pathname.endsWith("/" + action)) { 88 forwarded = true; 89 $("#a").click(); 90 } 91 }; 92 </script> 93</body> 94</html>
ブラウザがHTMLを新たに読み込んだ時のように振舞わせるために、「進む」、「戻る」の制御やスクリプトの実行などいろいろやってますが、これでもたぶんなんか考慮は漏れてます。「HTMLの中身全部」というのがなんとなく危険そうです。あくまでサンプルとして考えてください。
また上記コードは私のオリジナルですが、このような手法はSPA(Single Page Application)などを作成する際の一つの方法として名前がついています。「pjax
」というキーワードで調べてみてください。
投稿2016/11/22 08:32
総合スコア306
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/22 03:50
2016/11/22 04:24
2016/11/22 06:40 編集
2016/11/22 07:11