投稿する前に画像を表示できるようにしたいので、プレビュー機能を追加実装する。
プレビュー機能は見た目に動きをつける機能であるため、JavaScriptを使用して実装していく!
完成画面
下準備
- app/javascriptの中に、preview.jsというファイルを新規作成する。
- application.jsでpreview.jsを読み込む記述する。
- プレビュー画像を表示したい場所をビューファイルに指定する。
preview.js
// 新規投稿・編集ページでのみ、preview.jsが動作するように設定する
document.addEventListener('DOMContentLoaded', function(){
// 新規投稿・編集ページのフォームを取得
const postForm = document.getElementById('new_post'); //form_withのid
// プレビューを表示するためのスペースを取得
const previewList = document.getElementById('previews'); //プレビュー画像を表示する場所を追加したid
// 新規投稿・編集ページのフォームがないならここで終了。「!」は論理否定演算子。
if (!postForm) return null;
console.log("preview.jsが読み込まれました");
});
_form.html.erb
#プレビュー画像を表示させる設定→<div id="previews"></div>で指定
<%= form_with model: @post, id: 'new_post', local: true do |f| %>
<%= render 'shared/error_messages', model: f.object %>
<div class="message-field">
<%= f.text_field :text, placeholder: 'type a message' %>
</div>
<div class="image-field">
<div id="previews"></div>
<div class="click-upload">
<%= f.file_field :image %>
</div>
</div>
<div class="submit-btn">
<%= f.submit '送信' %>
</div>
<% end %>
プレビュー機能実装
- input要素(「ファイルを選択」ボタン)の値に変更があった場合、関数を発火させる
- 値の変更があった要素から、画像の情報を取得する
- 取得した画像情報のURLを生成する
- 取得した画像情報をブラウザへ表示するために、「HTMLの要素」をJavaScript側で生成する
preview.js
document.addEventListener('DOMContentLoaded', function(){
// 新規投稿・編集ページのフォームを取得
const postForm = document.getElementById('new_post');
// プレビューを表示するためのスペースを取得
const previewList = document.getElementById('previews');
// 新規投稿・編集ページのフォームがないならここで終了。「!」は論理否定演算子。
if (!postForm) return null;
// input要素を取得。name情報は検証ツールから確認すること!!
const fileField = document.querySelector('input[type="file"][name="post[image]"]');
// input要素で値の変化が起きた際に呼び出される関数
fileField.addEventListener('change', function(e){
// 古いプレビューが存在する場合は削除(最後に記述する)
const alreadyPreview = document.querySelector('.preview');
if (alreadyPreview) {
alreadyPreview.remove();
};
// 取得した画像ファイルの情報は、変数fileに格納する
const file = e.target.files[0];
// 取得した画像情報のURLを生成(生成されたURLはblobという変数に代入)
const blob = window.URL.createObjectURL(file);
// 画像を表示するためのdiv要素を生成
const previewWrapper = document.createElement('div');
previewWrapper.setAttribute('class', 'preview');
// 表示する画像を生成
const previewImage = document.createElement('img');
previewImage.setAttribute('class', 'preview-image');
// setAttributeメソッドを用いて生成したimg要素のsrc属性へ変数blobを設定する
previewImage.setAttribute('src', blob);
// 生成したHTMLの要素をブラウザに表示させる
previewWrapper.appendChild(previewImage);
previewList.appendChild(previewWrapper);
});
});
プレビュー画像のサイズをCSSで調整する
最後に画像サイズを指定したサイズ内に収まるように調整して完成!!
max-width: 100px;
max-height: 100px;
max-を使用すると、画像が100ピクセルを超える場合でも、指定したサイズの枠内に画像が表示されるようになるよ。