Rails5とBootetrapでモーダルウィンドウを作るまで

modalwindowアニメーション

rails5,bootstrapでmodalwindowを作成

Ruby on Rails 5.1.1でBootstrap4.0

もうなんかRailsでjqueyが終わりかけてるみたいな話もちらほら書いてありましたが、なんで終わっているのかもよくわかっていない状態のRails初心者のため、とりあえずBootstrapで実装を頑張っております。

そこでメモとしてオワコン化されているためか、ネットでも情報が少ないっぽい?ので一応残しておきます。

Rails5と BootstrapでAjax-modalform

ほとんど上記のサイトの丸パクリなのですが、このままやってもうまくいかなかったので、少しずつ修正しつつ、紹介していきます。

bootstrapの導入までは、以前記事にしたので困っている方いましたら参考にしてください。

とりあえず、scaffoldで作成。

コマンドライン

rails g scaffold user name:string
rails db:migrate
rails s 

そしたら、app/views/users/index.html.erb

の中身を確認し、

app/views/users/index.html.erb

<%= link_to 'New User', new_user_path %>

これを

app/views/users/index.html.erb

<%= link_to 'New User', new_user_path, class: "btn btn-lg btn-primary" %>

にします。

ただbootstrapに適用するためにclassをつけただけですね。

いよいよモーダル化

先ほどのlink_toでは、new.html.erbを呼び出す形になっていますのでそれをnew.js.erbに変えてしまおうということ。

やり方は簡単で、link_toのオプションにremote: trueを付け加えるのみ

最終的にボタンは以下のようになります。

app/views/users/index.html.erb


<%= link_to 'New User', new_user_path, remote: true, class: "btn btn-lg btn-primary" %>

これでこのリンク、ボタンをクリックするとnew.js.erbが呼び出されるのでnew.js.erbを作成。

中身は、

app/views/users/new.js.erb

$("#user-modal").html("<%= escape_javascript(render 'form') %>") ;
$("#user-modal").modal("show”) ;

jquey少しかじってれば、なんとなく読めるかと思うのですが、user-modalでidに対して、新規作成用のformをレンダリングすると言ったもの。
そして、それを表示しましょうみたいなことをしています。

そしたら表示するhtmlを作成します。

以下のコードを下の方にでも追加してみてください。これは上記サイトとは違った部分になります。モーダルウィンドウのデザインに少し関わってくるっぽいところです。

app/views/users/index.html.erb

<div class="modal fade" id="user-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"></div>

モーダルウィンドウを表示する部分になりますね。

_form.html.erbの修正

続いては、formの修正。

元から書いてあるformタグに関してremoteオプション追加して、

https://v4-alpha.getbootstrap.com/components/modal/

ここからサンプルコードを拝借して、修正した結果、以下のようになりました。

app/views/users/_form.html.erb

<div class="modal-dialog" role="document">
  <div class="modal-content">
    <%= form_with(model: user,remote: true) do |form| %>

    <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
      <ul>
        <% user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
        <% end %>
      </ul>
    </div>
    <% end %>

    <div class="modal-header">
      <h5 class="modal-title" id="exampleModalLabel">New message</h5>
      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>
    <div class="modal-body">

      <div class="form-group field">
        <%= form.label :name , class: "form-control-label"%>
        <%= form.text_field :name, id: :user_name, class: "form-control" %>
      </div>
    </div>
    <div class="modal-footer actions">
      <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      <%= form.submit class: "btn btn-primary"%>
    </div>
    <% end %>
  </div>
</div>

controllerの修正

続いて、controllerの修正です。リクエスト処理できるようにします。

  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
        format.js { @status = "success"}
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
        format.js { @status = "fail" }
      end
    end
  end

create処理後にcreate.js.erbを呼び出す。

create.js.erbの作成、表示部分の作成

create.js.erbは以下のようにする。

app/views/users/create.js.erb

app/views/users/create.js.erb

<% if @status == 'success' %>
$("tbody").append("<%= j(render("tr", user: @user)) %>");
<% elsif @status == 'fail' %>
alert('error!');
<% end %>
$("#user-modal").modal("hide”);

これは成功した場合と失敗した場合の処理。

続いて、表示の部分。今回はuser登録となりますので、user一覧が表示される部分。

app/views/users/_tr.html.erb

<tr>  
<td><%= user.name %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?'} %></td>
</tr>

参考にしたサイトもここで終了と書かれていたので、これでいける!と思ったらエラー発生。そんなにうまくいかないですよねー

意味わかんねーとしばらく悩んで、

controllerを修正

controllerのnewにjsを許可するコードが足りていないらしい。よくわかっていないけど、どこかのサイトに落ちてたものをそのまま流用。(笑)

そのサイト思い出し次第修正しておきます。すみません。

app/views/controller/users_controller.rb

def new 
	@user = User.new
		respond_to do |format| 
			format.html{ redirect_to @user, notice: 'User was successfully created.' }
			format.js {} 
		end
	end

とした。
しかしながらまだエラーは直らない。

無事解決!最終的な_form.html.erb

3時間くらいいろいろ試行錯誤した結果、

_form.htmlのuserに@が付いていないのが原因みたいで、@userとしたらうまくいった!

app/views/users/_form.html.erb
<div class="modal-dialog" role="document">
<div class="modal-content">
    <%= form_with(model: @user,remote: true) do |form| %>
    <% if @user.errors.any? %>
<div id="error_explanation">
      
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
	<ul>
        	<% @user.errors.full_messages.each do |message| %>
		<li><%= message %></li>
        <% end %>
      </ul>
    </div>
    <% end %>
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New message</h5>
      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>
<div class="modal-body">

<div class="form-group field">
          <%= form.label :name , class: "form-control-label"%>
          <%= form.text_field :name, id: :user_name, class: "form-control" %>
        </div>
    </div>
<div class="modal-footer actions">
      <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      <%= form.submit class: "btn btn-primary"%>
    </div>

    <% end %>
  </div>
</div>

これにて終了。

よくわかってない部分も多いですが、とりあえず目標とする動くところまでは実装できました。まだまだ勉強不足ですね。

少しずつ知識をつけていきます…!

来年見てバカだったなー俺と思えるように…!

コメントを残す

メールアドレスが公開されることはありません。

Follow
SHARE