質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

92.12%

  • JavaScript

    7181questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

【JavaScript】formの値を、jsonに変換して、postしたい。そして、action先に遷移したい。

解決済

回答 3

投稿 2016/11/22 11:51 ・編集 2016/11/22 14:47

  • 評価
  • クリップ 0
  • VIEW 756

やりたい事

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

  • 気になる質問をクリップする

    クリップした質問に回答があった場合に通知・メールを受け取ることができます。

    クリップした質問はマイページの「クリップ」タブからいつでも見ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+3

input要素に追加するとか。(他の要素も一緒にPOSTされますが、受け取り側で無視すればよいです)

$( 'form' ).submit( function() {
    // form値をJSONに変換
    var data = JSON.stringify( $( 'form' ).serializeArray() );
    $( 'form' ).html( '<input type="hidden" name="json" value="' + data + '">' );
} ); // 未テスト

追記:

じゃあフォームを追加すればよいのでは?

$( 'form' ).submit( function() {
    // form値をJSONに変換
    var data = JSON.stringify( $( 'form' ).serializeArray() );
    var action = $( 'form' ).attr( 'action' );
    $( 'form' ).after( '<form id="jsonpost" action="' + action + '"><input type="hidden" name="json" value="' + data + '"></form>' );
    $( 'form#jsonpost' ).submit();
    return false;
} ); // 未テスト

投稿 2016/11/22 12:00

編集 2016/11/22 12:18

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/11/22 12:07

    コメントありがとうございます。
    「出来るだけフロント側で対応してほしい。(他のデータは送らずJSONだけ送ってほしい)」
    と言われているため、提示いただいた内容だとNGです...申し訳ございません。

    キャンセル

  • 2016/11/22 12:14 編集

    To: hanakayui0628さん
    そういうことは、質問文に書いておいてください。

    キャンセル

  • 2016/11/22 12:14

    マイナスされた方は、どの辺りが問題点なのかをコメントして置いてください。今後に生かしたいので、よろしくお願いします。

    キャンセル

  • 2016/11/22 12:14

    > そういうことは、質問文に書いておいてください。
    申し訳ありません、明記しておきます。

    キャンセル

  • 2016/11/22 14:56

    回答文に追記しているのですが、御覧になられましたか?

    キャンセル

  • 2016/11/22 15:20

    返答遅くなり申し訳ございません!
    試してみて、JSONがsubmitで送信されるのは確認したのですが、JSONの形式が期待した結果となりませんでした...

    期待値:{"hoge": "111", "huga": "222"}
    実績値:{"json": {"hoge": "111", "huga": "222"}} // hiddenフィールドのname属性がJSONに入ってきてしまう。Railsの仕様??

    キャンセル

  • 2016/11/22 15:46

    json から取り出すのもだめなのですね。では serializeArray は使えませんね。

    同じように全要素をそれぞれhiddenで追加すればいいと思いますよ。

    キャンセル

  • 2016/11/22 15:47

    ここで回答するとマイナスが付くようですね。残念です。

    キャンセル

  • 2016/11/22 17:32

    なんか思い込みがあってそれに合わないとマイナス評価してくるみたいですね
    別に評価を上げてほしいとは思いませんが、回答するだけ無駄なような気がします

    キャンセル

  • 2016/11/28 09:58

    私はマイナスにしました。

    どこが悪いか聞いたり、マイナス評価の理由を邪推する前に、この回答のコードをテストして本当にJSONがPOSTできるか確認してみてはいかがでしょうか。

    キャンセル

  • 2016/11/28 14:44

    To: guest1213さん
    回答されたものを見て、「Content-Type:application/jsonのデータのPOST」だということにやっと思い至りました。なので、「この回答のコードをテストして本当にJSONがPOSTできるか」は確認のしようが有りません。(formのPOSTを受け取ってそれをJSONにすると思っている状態では確認しています)ひとことコメントして欲しかったです。

    キャンセル

+3

状況がよくわからないのですが
ajaxでpostしたあとpostしたら二重投稿になりませんか?
むしろ同じデータをおくるのであればajaxでおくらずにpostするだけでよいのでは?

仮にajaxでpostしたあとにページの遷移をするだけなら
location.hrefでデータを送らない遷移ではいけないのでしょうか?

 追記

とりあえずajaxの部分はこうしてください

<script>
$(function(){
  $('form').on('submit',function(){
    var data = {};
    $(this).find('input[name]').each(function(){
      data[$(this).prop('name')]=$(this).val();
    });
    console.log(JSON.stringify(data));
    $.ajax({
    type: $('form').attr('method'),
    url:  $('form').attr('action'),
    dataType: 'text',
    data: data,
    success:function(d){
      console.log(d);
    },
    });
    return false;
  });
});

</script>
<form method="post" action="xxx.php">
<input type="text" name="aaa" value="123">
<input type="hidden" name="bbb" value="xyz">
<input type="submit" value="go">
</form>

投稿 2016/11/22 12:31

編集 2016/11/22 16:07

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/11/22 12:50

    > ajaxでpostしたあとpostしたら二重投稿になりませんか?
    本来のsubmitが動かないようにreturn false;としています。

    > 同じデータをおくるのであればajaxでおくらずにpostするだけでよいのでは?
    フロントからJSONを送りたいので、formを送るだけのpostでは要件を満たせないです。

    > 仮にajaxでpostしたあとにページの遷移をするだけなら
    > location.hrefでデータを送らない遷移ではいけないのでしょうか?
    画面Aからaction"hoge"を実行して、hogeに遷移したいので、単なる遷移ではダメですね...申し訳ないです。

    キャンセル

  • 2016/11/22 13:24

    >本来のsubmitが動かないようにreturn false;としています。

    それは見てわかっているのですが、その後飛び先にいくんですよね?
    そしたら次の2択しかないでしょ?
    (1)二重投稿だってわかっていてpostする
    (2)postせずにlocation.hrefでとぶ(ajax送信後)

    postしてないけどpostしたような表示にしたいというのは道理に合いません
    もちろんajaxでページ取得した結果をhtmlとして表示するということは可能ですが
    それは遷移先に移動することではありませんので

    キャンセル

  • 2016/11/22 15:40 編集

    Ruby on Railsのアクション"hoge"に対してPOSTしたいので、
    ただの画面遷移では意味がないです。

    また、ajaxで処理するだけだとhogeの画面に遷移しないので、
    ajaxを使って処理する"だけ"、というのもNGです。

    キャンセル

  • 2016/11/22 16:11

    ajaxの部分はサンプルをつけておました
    私の認識が正しければ命題が矛盾しているためご提示のことは
    実現不可能ですが、とりあえずajaxで送ることは可能です

    キャンセル

checkベストアンサー

+2

サーバー側がContent-Type:application/jsonのデータのPOSTしか受け付けず、かつ結果をContent-Type:text/htmlで返してくる、ということですね。そしてそのHTMLを表示したいと。

この場合、HTMLのformではJSONはPOSTできませんので、実現不可能です。よってAjaxなり、他の方法でJSONをPOSTするしかないのですが、その場合は「画面遷移」が不可能です。

なので私が思いつく案としては受け取ったHTMLで現在のドキュメントの内容を書き換えて「遷移に見せかける」くらいしかありませんが、以下のサンプルのような感じではどうでしょうか。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>a</title>
  <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
  <form action="b.html">
  </form>
  <button id="a">submit</button>
  <script>
    var data = {"message": "hello"};
    var action = $("form").attr("action");
    var forwarded = false;
    $("#a").on("click", function() {
      $.ajax({
        type: "POST",
        url: action,
        dataType: "html",
        contentType: "application/json",
        data: JSON.stringify(data),
        success: function(res) {
          // レスポンスからDOMを構築してscriptタグだけ復元可能なようにしておく
          newHtml = new DOMParser().parseFromString(res, "text/html");
          var scriptElements = Array.prototype.map.call(
            newHtml.getElementsByTagName("script"), function(elem) {
              return elem;
            }
          );
          var scriptParents = [];
          var scriptNexts = scriptElements.map(function(elem) {
            scriptParents.push(elem.parentNode);
            for(;elem.nextSibling !== null && elem.nextSibling.tagName === "script";
                elem = elem.nextSibling) {}
            return elem.nextSibling;
          });
          var i = 0;
          for(i = 0; i < scriptParents.length; i++) {
            scriptParents[i].removeChild(scriptElements[i]);
          }

          // 現在のドキュメントを空(<html>のみ)にする
          while(document.documentElement.firstChild) {
            document.documentElement.removeChild(document.documentElement.firstChild);
          }
          // レスポンスのDOMから現在のドキュメントに要素を移動させる
          while(newHtml.documentElement.firstChild) {
            document.documentElement.appendChild(
              newHtml.documentElement.removeChild(newHtml.documentElement.firstChild));
          }
          // scriptの復元
          var loaded = Promise.resolve();
          for(i = 0; i < scriptParents.length; i++) {
            (function(i) {
              loaded = loaded.then(function() {
                return new Promise(function(resolve) {
                  var script = document.createElement("script");
                  for(var j = 0; j < scriptElements[i].attributes.length; j++) {
                    var attr = scriptElements[i].attributes.item(j);
                    script.setAttribute(attr.name, attr.value);
                    if(attr.name === "src") {
                      // ファイルを読み込んでいる場合は以降のコードは読み込み終わってからでないといけない
                      script.onload = function() { resolve(); };
                    }
                  }
                  scriptParents[i].insertBefore(script, scriptNexts[i]);
                  script.textContent = scriptElements[i].textContent;
                  if(!script.onload) { resolve(); }
                });
              });
            })(i);            
          }

          // 「戻る」対応
          if(!forwarded) {
            history.pushState(null, null, action);
          }
          window.onpopstate = function(){
            location.reload();
          };
        },
      });
    });
    // 「進む」対応
    window.onpopstate = function(){
      if(location.pathname.endsWith("/" + action)) {
        forwarded = true;
        $("#a").click();
      }
    };
  </script>
</body>
</html>

ブラウザがHTMLを新たに読み込んだ時のように振舞わせるために、「進む」、「戻る」の制御やスクリプトの実行などいろいろやってますが、これでもたぶんなんか考慮は漏れてます。「HTMLの中身全部」というのがなんとなく危険そうです。あくまでサンプルとして考えてください。

また上記コードは私のオリジナルですが、このような手法はSPA(Single Page Application)などを作成する際の一つの方法として名前がついています。「pjax」というキーワードで調べてみてください。

投稿 2016/11/22 17:32

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

92.12%

関連した質問

  • 解決済

    post送信の方法を教えて頂けませんか

    前提・実現したいこと 複数選択可能なチェックボックスにおいて、未チェックなら送信ボタンをクリックできないようjqeryで制御し、チェックが付いたらpost送信と同時にindexの

  • 解決済

    PHPとajaxによる検索について

    検索機能の作り方で困ったので質問させていただきます。 現在、PHPとMySQLとajaxで検索機能を作っています。 仕様としましては、リアルタイムに検索結果を出したかっ

  • 解決済

    画面遷移せずにデータをPOSTしたい

    前提・実現したいこと 管理画面と公開画面があり、管理画面で入力したHTMLタグを公開画面に反映させようとしています。 発生している問題・エラーメッセージ 管理画面でPOS

  • 解決済

    複数サブミットで、一つだけ新しいウィンドウで開きたい

    1つのフォーム内に複数のサブミットがあり、  一つは、同一ウィンドウでフォームの値をもっていき もう一つは、別ウィンドウで値を持っていきたいです。 色んなサイトを調べて以下の

同じタグがついた質問を見る

  • JavaScript

    7181questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

閲覧数の多いJavaScriptの質問