ajaxちょっと復習

1Jsファイル内

フォームタグのid名を取得して送信ボタンが押されたらデフォルトのhtmlレスポンスになるのを防いでおく

 

$('フォームタグのid名').on('submit', function(e){

 e.preventDefault()

});

 自分はrailsで使うことが多いだろうから追記しておくけど、form_forで作ったformでは自動的にid属性が付くようになっているので検証ツールでid名を確認する。デフォルトだとnew_hogehoge。hogehoge部分は渡したインスタン名なので、例えばnew_message等といったid名がついているはず 

 

2JSファイル内

送信ボタンが押されたらmessagesコントローラーのcreateアクションがajaxで動くようにする

 

①前回の続きなので今回のthisはform要素のこと

②var formData = new FormData(特定のform要素)という感じで変数formDataにオブジェクトFromDataを入れとく。これがFormDataオブジェクトを使う時の基本で、オブジェクト化したものにどんな振る舞いをさせられるのかは調べて

送信先のurlが欲しいのでformタグ内のaction属性を取得して変数urlに入れとく。これによって正しいidが入ったurlを取得できるはず。

ajax関数のオプションを適切に指定する

 

①②

var formData = new FormData(this);

var url = $(this).attr('action');

$.ajax({

  url: url,

 type: 'Post',

 data: formData,

 dataType: 'json',

 processData: false,

 cententType: false

});

 

 3コントローラーのcreateアクション

メッセージを保存して、respond_toでhtmlとjsonの場合で処理を分ける

 一例

def create

  @message = @group.messages.new(message_params)

   if @message.save

        respond_to do |format|

           format.json

        end

  else

     省略

  end

end    

 

4ファイル作成

アクション名.json.jbuilderを普通の場合と同じようにviewファイル内の適切なフォルダに作成する。今回はcreate.json.jbuilderを作成する。

作る時は.html.erbと同じノリでいいけど中身に書くのは

json.user_name @message.uer.name

json.image @message.image_url

といったデータの受け渡しといった感じ。

書き方参照

https://qiita.com/ryouzi/items/06cb0d4aa7b6527b3645

 

5JSファイル内

①関数builHTMLで仮に引数をmessageとしてそのmessage部分に渡されるjsonのデータが入ることを想定した出力用のhtmlを組み立てて変数htmlに格納しておく。

②送信ボタンが発火すると3と4でやったようにcreateアクションでデータが保存された上でjson形式だった場合はcreate.json.jbuilderでデータの受け渡しが行われる。

③送信ボタンで発火する関数内にajax通信が成功(done)した時には先ほどviewファイルのjbuilderで受け取ったデータを引数dateとしてそのまま作って置いた関数buildHTMLに引数として渡し、message部分を受け取ったdataに置き換えたhtmlを組み上げた上で改めて変数htmlに格納する(スコープの問題?)という手法でajax通信でページの一部を書き換える。ただし実際に書き換えるのは次の6の部分でまだ変数htmlの準備が整った段階である。

 

function buildHTML(message){

  var html =

`テンプレートリテラル内 shilf +@で打てるバッククオートで囲む。

  htmlをちゃんと書いて変数htmlに代入

};

 

$('new_message').on('submit', function(e){

省略

  $.ajax({

            省略

   })

          .done(function(data){

          var html = buildHTML(data);

            })

省略

 

テンプレートリテラル内がわかりづらいかもしれないのでざっくりだが具体的に書くと下みたいな感じ

基本的にはそれ自体がポンと付け足されても違和感ないように箱の部分から組んでやるって感じかな。当たり前だが、作ったビューファイルで受け取ったデータが入る部分をところどころ仮にデータの部分をmessageとして組み込んでいるので注意。

ざっくり具体例

function buildHTML(message){

    var html =

    ` <div class = "upperside">

          ${message.user_name}

     </div>

     <div class= "lowerside">

         <img src =${message.image} >

     </div>

     return html;

     '

};

 

6JSファイル内

出力する場所を等を整える

例えばたくさんのメッセージの一番下にテンプレートリテラル内で作成したhtmlをくっつけようとする場合。出力する場所のクラスがmessagesだったとして、データの通信とhtmlの生成には成功しているという状態を想定しているので.doneメソッド内でjqueryセレクタを使いそこにappenすればいい。送信フォームはリセットしておく。具体的には先ほどのdoneメソッドを修正して

  .done(function(data)){

          var html = buildHTML(data);

          $('.messages').append(html);

          $('.form')[0].reset();

       })

とする。

 

7その他

  ①非同期通信失敗時の処理も書く

通信成功時しか書いてなかったので(.done関数の処理)、通信失敗時の処理も書いておく

くどいが流れおさらい

送信ボタンが押された時に発火する関数内で、どう言ったajax通信するかを

$.ajax({})に書いて、

その次に成功時なら.done(funcation(data){})、

失敗時なら.fail(function(){})

を並べるといった書き方になる。

 

②ボタンを連続で押せるようにする

普通はreloadしないと送信ボタン押せない設定になってるので

 $('ボタンのクラス名かid名').prop('disabled', false)

等としてその設定を無効にする。ちなみにセレクタは今までformを選択していたが、今回はボタンに関する物なのでボタンの部分をセレクトする。

 

③増えた分スクロールする

$('.messages').animate({ scrollTop: $('.messages')[0].scrollHeight}); 

 

.messagesは作ったhtmlを出力したい場所。

scrollTopで:の後ろの部分だけスクロールする

$('.messages')[0].scrollHeight はメッセージが入ったdiv要素のスクロールできる高さを取得

 

追記予定