2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails7で更新成功時にBootstrapのToastsを表示する

Last updated at Posted at 2022-03-15

Rails で bootstrap を使うことになったので、せっかくだから更新成功時に Toasts を表示しよう考えました。

Bootstrap の Toasts は自分で初期化する必要があるのですが、window の load イベントを契機に初期化しようとして失敗しました。
というのも Rails には Turbolinks という機能があって、History API を使って遷移を行うために、ページ遷移時に window の load イベントが発火しないのです。

Toasts の初期化の仕方や show の呼び方をいろいろ試した結果、とりあえず表示するところまではたどり着けたので、備忘録代わりに記録を残します(もっと上手いやり方があったら知りたい)。

Docker で環境を作っているので、そこらへんは適宜読み替えてください。

環境

  • Ruby 3.1.1
  • Ruby on Rails 7.0.2
  • Docker 20.10.10, build b485636
  • Docker Compose v2.2.3
  • node.js v16.14.0
  • bootstrap 5

インストール

https://qiita.com/mkt1234/items/b852eeeb213e46702236 にある方法でインストールしました。

Rails をインストールするときのオプションに -css=bootstrap を追加しました(Bootstrap のインストールはこれが一番楽だと思う)。

docker compose run --rm --no-deps web rails new . --force --css=bootstrap -d=postgresql

ひな形を作成

まずは scaffold で User を作成します。

docker compose run --rm web rails g scaffold User name:string

Bootstrap Toasts の作成

各ページに Toasts を埋め込むのは大変なので、body の直下に 1 つだけ埋め込んで、render の notice で制御するようにしました。
notice と flash の使い分けが良く分からなかったので notice を使っています。

Toasts 用の erb を作成

notice の有無で data-controller 属性の表示を切り替えるようにしました(他に良いアイデアが思い浮かばなかった……)。
この data-controller 属性がポイントのようです。

position-fixed start-50 translate-middle-x は位置調整なのでお好みで。

app/views/common/_toast.html.erb
<div class="toast position-fixed start-50 translate-middle-x"
    role="alert" aria-live="assertive" aria-atomic="true"
    <%= !!notice && "data-controller=toast" %>>
  <div class="toast-header">
    <strong class="me-auto">成功</strong>
    <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
  </div>
  <div class="toast-body">更新成功</div>
</div>

Toasts を body の下に配置

body の下に _toast.html.erb を配置します。

app/views/layouts/application.html.erb
...
  <body>
    <%= render "common/toast" %>  
    <%= yield %>
  </body>
...

既存の notice の表示を削除

notice の文言は Toasts に置き換えるので、各 erb の先頭にある <p style="color: green"><%= notice %></p> を消します(index.html.erbの先頭のやつも消しておく)。

app/views/users/show.html.erb
<%= render @user %>

<div>
  <%= link_to "Edit this user", edit_user_path(@user) %> |
  <%= link_to "Back to users", users_path %>

  <%= button_to "Destroy this user", @user, method: :delete %>
</div>

Stimulus の設定

Stimulus の Controller を作ります(言い方あっているのか?)。
ここが一番の苦労したポイント。

data-controller="toast" を指定した要素がロードされた瞬間に、この controller(toast_controller.js) の connect() が呼ばれるので、そこで Toasts を初期化します。

初期化したらすぐに .show() を呼んで Toasts を表示させます。

app/javascript/controllers/toast_controller.js
import { Controller } from '@hotwired/stimulus'
import * as bootstrap from 'bootstrap'

export default class extends Controller {
  connect() {
    new bootstrap.Toast(this.element, { delay: 2000 }).show()
  }
}

toast_controller を読み込みます。

app/javascript/controllers/index.js
import { application } from './application'

import ToastController from './toast_controller'
application.register('toast', ToastController)

precompile

app/javascript 以下のファイルを precompile します。
自分で package.json に sciprts.build などを作っていれば docker compose run --rm web yarn build の方が速いです。

docker compose run --rm web rails assets:precompile

表示

作成・更新成功時に Toasts が表示できるようになりました。
あとは自分好みに Toasts のスタイルを変えるだけ。
toasts.png

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?