DailyOscar

루비온레일즈 부트스트랩 모달 다이얼로그 본문

IT

루비온레일즈 부트스트랩 모달 다이얼로그

OscarHS 2018. 7. 25. 02:58
반응형

부트스트랩 모달 다이얼로그 In 레일즈!



https://getbootstrap.com/docs/4.0/components/modal/   부트스트랩 모달 다이얼로그


# TODO

간단한 Post 모델, 컨트롤러를 생성하고 create 버튼을 눌렀을 때 form 페이지로 리다이렉트 하는 것 대신,

form이 들어있는 모달 다이얼로그 띄워 생성해보자.





개발환경

c9 Ruby on Rails


ruby 2.5.1, Rails 5.2.0에서도 OK


Gemfile에 bootstrap 추가 (Rails 5.2.0 에서는 jquery-rails 도 추가)



bundle install


---------------------


assets/javascripts/application.js에 bootstrap 추가

assets/stylesheets/application.css의 확장자를 scss로 바꿔준다 (application.scss) 그 후 bootstrap 추가


 js                               scss




---------------------------


빠른 진행을 위해 scaffold로 Post 모델, 컨트롤러를 생성

rails g scaffold Post title

  db/migrate/xxxxxx_create_posts.rb



rake db:migrate  (SQLite가 아닌 다른 DB를 쓴다면.. migrate 전에 create)

 db/schema.rb


---------------------


준비 끝



모달 다이얼로그를 띄우기 위한 흐름 정리


사용자가 Create 링크 클릭 -> 라우팅을 통해 지정된 액션 수행 후 js 렌더링 -> 파셜 렌더링을 통해 form을 띄움



--------------------------------


기존 scaffold를 통해 생성된 코드에서 create 링크를 클릭하게 되면 #new 에서 new.html.erb를 렌더링하고 이곳(new.html.erb)에서 파셜렌더링을 통해 _form.html.erb가 띄워지게 된다.


1) 라우팅 작성

scaffold를 통해 생성하면 config/routes.rb에 resources :posts 라고 작성되어 있다.


localhost:3000/rails/info/routes 에 들어가보면 resources :posts를 통해 생성되는 라우팅 종류를 알 수 있다.




실행하고 url치기 귀찮으면 콘솔에 rake routes라고 작성해도 같은 정보가 뜸


root 'posts#index' 를 통해 랜딩페이지를 지정하고.

기본으로 new가 있는 것을 확인했으니 넘어가자!


2) create 링크(버튼)을 클릭했을 때 모달 다이얼로그를 띄우기 위해서 create 링크를 수정하고, view에 <div id="모달들어갈 div"> 를 추가해주어야 한다.


scaffold로 자동 생성된 view에서 new post 하는 곳은 index.html.erb 밖에 없다.

기본으로 생성된 링크를 클릭하게 되면 new action으로 넘어가서 new.html.erb를 띄우게 된다. 

우리는 rails-ajax를 사용하여 new액션을 수행하고 new.js.erb를 렌더링하게 만들 것이다.


위의 link_to 를 다음과 같이 수정하자.

1
2
3
4
5
6
7
<%link_to 'New Post', new_post_path , remote: true, data: { target: '#modal-window', toggle: 'modal' }, class: 'btn btn-primary'%>
<div id="modal-window" class="modal hide fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">    
    </div>
  </div>
</div>
cs

주의해서 볼 것은 link_to의 remote: true 부분.  -> rails-ajax (페이지 이동이 일어나지 않고, 액션을 수행한다)

data: {target: '#modal-window', toggle: 'modal'} 부분 -> bootstrap modal dialog를 띄울 div id지정, 클릭하면 띄움


그리고 그 밑에 id="modal-window" 를 갖고 있는 div 태그와 child 들이다.  -> 다이얼로그가 들어가는 코드 부분




3) posts_controller.rb 의 new 액션 수정

scaffold로 생성 된 new 액션은 다음과 같이 작성되어 있다. 


현재 new 액션이 수행되면 Post 모델에 있는 정보를 갖고 new.html.erb가 렌더링 된다.



이것을 컨트롤러가 ajax 요청에 대해 응답을 돌려줄 수 있도록 new 액션을 다음과 같이 수정


1
2
3
4
5
6
7
8
  # GET /posts/new
  def new
    @post = Post.new
    respond_to do |format|
      format.html
      format.js
    end
  end
cs


4) 우리는 new.js.erb를 렌더링되게 할 것이므로 new.js.erb를 생성하자


기존에 있던 new.html.erb는 _new.html.erb로 파일명 변경, 그리고 

<%= render 'form' %> 외의 것들은 지우자.




5) new.js.erb를 다음과 같이 작성

1
2
$("#modal-window").find(".modal-content").html("<%= j render 'posts/new' %>");
$("#modal-window").modal('show');
cs


1번 라인: modal-window 란 id를 가진 요소를 찾고, 그 요소의 자식태그 중 modal-content 란 class를 가진 요소를 찾아서

그 요소의 값을 지정한다.


j는  escape_javascript의 별칭(Alias)이다.


악성 유저가 악성 스크립트를 페이지에서 실행하지 못하도록 캐리지 리턴, ', " 에 대해서 이스케이프 처리 한다.


2번 라인: 모달을 보이게 한다.




6) _new.html.erb에서는 form을 렌더링한다.

부트스트랩 모달을 제대로 보여주기 위해서는

항목에 class 지정이 필요하다.


scaffold로 생성된 form은 다음과 같다. 



지정해야하는 태그 목록

.modal-header (모달의 헤더)

.modal-title     (모달의 제목)

.modal-body    (모달의 몸체)

.modal-footer   (모달의 하단)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div class="modal-header">
  <h5 class="modal-title" id="exampleModalLabel">Post 생성</h5>
  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
 
<%form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
 
      <ul>
      <% @post.errors.full_messages.each do |message| %>
        <li><%message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
<div class="modal-body">
  <div class="field">
    <%f.label :title %><br>
    <%f.text_field :title %>
  </div>
</div>
 
<div class="modal-footer">
  <div class="actions">
    <button type="button" class="btn" data-dismiss="modal" aria-label="Close">취소</button>
    <%f.submit class: 'btn btn-primary'%>
  </div>
</div>
<% end %>
 
cs


header에는 Post 생성이라는 title과 닫기 버튼을 추가했다.


form의 필드를 묶어 modal-body를 지정했고


submit과 취소를 footer에 놓았다.



닫기를 위한 태그에서 data-dismiss="modal" 부트스트랩 라이브러리에 속해있는 것으로

자바스크립트의 추가 작성 없이 자연스럽게 창이 사라지도록 기능한다.


------------------



동작확인






물론 우리는 Edit.html.erb을 처리하지 않았기 때문에

Edit 화면에서 취소버튼은 동작하지 않음. Update Post는 동작함.




그럼 끝!



반응형
Comments