はじめに
非同期処理に合わせて、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);
};
フラッシュメッセージの実装
パーシャル(共通のファイル)として、他のビューファイルからも呼び出して使えるようにしています。
<div>
<% flash.each do |message_type, message| %>
<div class="flash-message <%= message_type %>"><%= message %></div>
<% end %>
</div>
他のビューファイルで呼び出す
<div class="flash-message-container">
<%= render 'shared/flash_message' %>
</div>
サーバー側
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リクエストを送信しています。
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 %>">
動作確認結果
イベントを削除した後のフラッシュメッセージ表示/非表示の例です。
まとめ
実装を通じてflashの仕組みやJavaScriptのいろんなプロパティやメソッドへの理解も深まりました。
JavaScriptの基本を理解したい方のお役に立てれば幸いです。