30
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails/JavaScript】非同期のフラッシュメッセージ表示

Last updated at Posted at 2024-05-26

はじめに

非同期処理に合わせて、Javascriptでフラッシュメッセージも非同期的に表示する実装についてまとめました。

実装内容

フラッシュメッセージを表示する関数

jsの各メソッドについては、後述の解説にまとめています。

  function displayFlashMessage(data) {
    const div = document.createElement('div');
    div.className = 'flash-message';
    div.textContent = data.message;

    const flashContainer = document.querySelector('.flash-message-container');
    flashContainer.appendChild(div);
    div.classList.add(data.message_type);

    //js側でstyleを設定(画面の中央に固定で配置する)
    flashContainer.style.position = 'fixed';
    flashContainer.style.top = '50%';
    flashContainer.style.left = '50%';
    flashContainer.style.opacity = 0.9;
    flashContainer.style.zIndex = 99;
    // jqueryのfadeOutメソッドで5秒後に非表示
    $(div).fadeOut(5000);
  };

フラッシュメッセージの実装

パーシャル(共通のファイル)として、他のビューファイルからも呼び出して使えるようにしています。

app/views/shared/_flash_message.html.erb
<div>
  <% flash.each do |message_type, message| %>
    <div class="flash-message <%= message_type %>"><%= message %></div>
  <% end %>
</div>

他のビューファイルで呼び出す

app/views/events/index.html.erb
<div class="flash-message-container">
  <%= render 'shared/flash_message' %>
</div>

サーバー側

app/controllers/events_controller.rb
  def destroy
    @event.discard
    if @event.discarded?
      render json: { status: 'success', message_type: 'notice', message: "イベント削除しました", event_data: @event }, status: 200
    else
      render json: { status: 'error', message_type: 'alert', message: "イベント削除に失敗しました" }, status: 400
    end
  end
  • 処理が成功(もしくは失敗)した場合のフラッシュメッセージのタイプとメッセージ内容をJSONで送ります。
  • message_typeとmessageは、前述のフラッシュメッセージと同じキー名を設定しています。

フロント側

前提として、今回はfetchによってDELETEリクエストを送信しています。

flash.js
    try {
        const url = `http://localhost:3000/events/1`;

        const response = await fetch(url, {
            method: 'DELETE',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
        });

        if(response.ok) {
            // JSONを受け取り、JavaScriptオブジェクトにparseします(awaitでparseが完了するまで待つ)
            const data = await response.json();
            // フラッシュメッセージの関数を呼び出す
            displayFlashMessage(data);
        } else {
            const data = await response.json();
            displayFlashMessage(data);
        }
    } catch {
      console.error( e.name, e.message );
    }

解説

前述のフラッシュメッセージ関数内の処理をメインに解説しています。

Document.createElement()

引数に指定されたHTML要素を生成します(ここでは<div>を生成しています)
生成したdivはローカル変数(定数)へ格納しています。

const div = document.createElement('div');

className

class属性を取得または設定します。

div.className = 'flash-message';

textContent

ノード内のテキストを取得または設定します。
ノードとは、「HTML(DOMツリー)の一つ一つの要素」のことです。
ここでは、先ほどclass属性flash-messageを設定したdivタグに、サーバーから返却されたレスポンス内のmessageの値を設定しています。

div.textContent = data.message;

(補足)
開発者ツールの要素タブでノードを指定>プロパティを選択するとtextContentに値が入っていることが確認できました。

querySelector()

指定された CSS セレクタの最初の要素を返します。
ここではフラッシュメッセージを呼び出すファイルのdivに指定されたclass属性を取得しています。

const flashContainer = document.querySelector('.flash-message-container');

appendChild()

特定の親ノードの子ノードリストの末尾にノードを追加します。
先ほどのflashContainer変数にdivを追加します。
class属性flash-messageとtextContentの中身が入ったdivタグを指しています。

flashContainer.appendChild(div);

classList

特定の要素のクラス名を追加、削除、参照などすることができるプロパティです。
今回はclassList.addで先ほどのdivに対して、サーバーからのmessage_typeをclass名として追加しています。

div.classList.add(data.message_type);

(補足)
追加されたclass属性は前述のフラッシュメッセージflash-messageに付与されます

<div class="flash-message <%= message_type %>">

動作確認結果

イベントを削除した後のフラッシュメッセージ表示/非表示の例です。
asyncflash.gif

まとめ

実装を通じてflashの仕組みやJavaScriptのいろんなプロパティやメソッドへの理解も深まりました。
JavaScriptの基本を理解したい方のお役に立てれば幸いです。

参考記事

30
6
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
30
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?