#はじめに
Railsでオリジナルアプリを制作しています。このアプリに画像投稿機能を実装しました。画像をアップロードした後(データベースに保存する前)の状態でプレビューを表示しましたので、書き記します。
※コードひとつひとつに解説を挟むので、最後に完成コードを載せています。
#目次
1.事前準備
2.プレビュー機能の実装
#1.事前準備
JavaScriptを使用しますので、jsファイルを準備します。ページが読み込まれたときに動作するように定義します。
document.addEventListener('DOMContentLoaded', function(){
const ImageList = document.getElementById('image-list');
});
なお、getElementByIdで取得するimage-listは、html上のdivタグのid名です。このdivタグにプレビューを表示します。そのため、htmlに追記します(今回は送信ボタンの下に配置しました)。
<%= f.file_field :image %>
<%= f.submit '送信' %>
<div id="image-list"></div>
また、作成したjsファイルが読み込まれるようにapplication.jsも編集します。コメントアウトしたturbolinksは画面遷移を高速化するGemです。ページ内の情報を全て読み込まず、HTMLだけを読み取るそうです。だからJavaScriptで設定したイベントが発火しない場合があります。
// require("turbolinks").start() // コメントアウトする
require("@rails/activestorage").start()
require("channels")
require('./preview') // 追記する
#2.プレビュー機能の実装
全部で3ステップ。
**2-1.画像情報の取得
はじめに画像情報を取得し、URLを生成します。画像情報の取得はinput要素の値に変更があった場合に行います。
document.addEventListener('DOMContentLoaded', function(){
const ImageList = document.getElementById('image-list');
document.getElementById('desk_image').addEventListener('change', function(e){
//↑desk_imageは画像選択ボタンのid//
const file = e.target.files[0];
const blob = window.URL.createObjectURL(file);
});
});
選択した画像は、発火したイベントe、targetの中のfilesという配列に格納されています。それをfile変数に定義し、window.URL.createObjectURLでURLを生成します。
2-2.取得画像の表示
createElementで取得画像を入れ込むdiv要素とimg要素生成します。その後生成した要素をブラウザに表示します。
document.addEventListener('DOMContentLoaded', function(){
const ImageList = document.getElementById('image-list');
document.getElementById('desk_image').addEventListener('change', function(e){
const file = e.target.files[0];
const blob = window.URL.createObjectURL(file);
// 画像を表示するためのdiv要素を生成
const imageElement = document.createElement('div');
// 表示する画像要素を生成し、画像を入れ込む
const blobImage = document.createElement('img');
blobImage.setAttribute('src', blob);
// 生成したHTMLの要素をブラウザに表示させる
imageElement.appendChild(blobImage);
ImageList.appendChild(imageElement);
});
});
appendChildで指定した親要素の中に要素を追加する(使い方:親要素.appendChild(子要素))。
2-3.エラー回避と編集可能にする
2-2までで画像は表示されるようになりました。しかし、画像投稿ページ以外ではコンソール上でエラーが表示されます。これを回避するため条件分を追加します。URLにnew及びeditがある場合(画像の新規投稿、編集時)に適用するように記述します。
if (document.URL.match( /new/ ) || document.URL.match( /edit/ )) {
document.addEventListener('DOMContentLoaded', function(){
const ImageList = document.getElementById('image-list');
ーーーーーーーーーーーーーーー中略ーーーーーーーーーーーーーーーーーー
// 生成したHTMLの要素をブラウザに表示させる
imageElement.appendChild(blobImage);
ImageList.appendChild(imageElement);
});
});
}
画像を編集するときは、既存のプレビューを削除した後に新しい画像のプレビューを表示するようにする。
if (document.URL.match( /new/ ) || document.URL.match( /edit/ )) {
document.addEventListener('DOMContentLoaded', function(){
const ImageList = document.getElementById('image-list');
document.getElementById('message_image').addEventListener('change', function(e){
// 画像が表示されている場合のみ、すでに存在している画像を削除する
const imageContent = document.querySelector('img');
if (imageContent){
imageContent.remove();
}
const file = e.target.files[0];
const blob = window.URL.createObjectURL(file);
const imageElement = document.createElement('div');
const blobImage = document.createElement('img');
blobImage.setAttribute('src', blob);
imageElement.appendChild(blobImage);
ImageList.appendChild(imageElement);
});
});
}
以上