RubyでECサイトのクローンを作成中に出品画面において複数枚画像投稿機能を実装していく中で、5枚以上の画像制限を設けようとした際の学習メモです。
この記事を見れば、拙いながらも、複数枚のプレビュー機能の実装と、枚数制限を実装することができます。
####学習環境
macOS BigSur
ruby-2.6.5
Rails 6.0.3.6
mulutipleオプションで複数枚の画像投稿機能を実装
ビュー内に、file_fieldを使って画像投稿できる要素を記載します。
(省略)
<%= f.file_field :images, name: 'item[images][]', id:"item-image", multiple: true %>
(省略)
multiple: true
オプションで画像を複数選択することができるようになります。(詳細はこちら)
この複数選択機能に枚数制限をかけようと思い、私が実装したのは、5枚以上の画像を選択した際に、file_field要素内のfilelistからオブジェクトを削除する方法で枚数制限をかけようと思いました。
そこで、JavaScriptを使ってfilelistからオブジェクトを削除する方法を調べたところ、このサイトを参考にして、filelistを削除することができました。
Filelistを削除するコード
document.getElementById('item-image').value = "";
先程ビューで記載したfile_fieldに設定されたdataTransferオブジェクトをgetElementById
で取得し、そのvalueに空白を代入すると、選択ファイルを削除することができました。
拙いですが、全体のコードとしては、このような感じです。
document.addEventListener('DOMContentLoaded', function (){
if (document.getElementById('item-image')){
const imageList = document.getElementById("image-list");
const createImageHTML = (blob) => {
const imageElement = document.createElement('div');
imageElement.setAttribute('class', "image-element")
let imageElementNum = document.querySelectorAll('.image-element').length
const blobImage = document.createElement('img');
blobImage.setAttribute('src', blob);
blobImage.setAttribute('id', 'add-image');
const inputHTML = document.createElement('input');
inputHTML.setAttribute('id', `item_image_${imageElementNum}`);
inputHTML.setAttribute('name', 'image[images][]');
inputHTML.setAttribute('type', `file`);
imageElement.appendChild(blobImage);
imageList.appendChild(imageElement);
};
document.getElementById("item-image").addEventListener("change", function(e){
const removeContents = document.querySelectorAll("#add-image");
const removeElements = document.querySelectorAll('.image-element');
if (removeContents){
removeContents.forEach(function (removeContent){
removeContent.remove();
})
removeElements.forEach(function (removeElement){
removeElement.remove();
})
}
const forNum = e.target.files.length
if (forNum < 5){
for (let i = 0;i < forNum; i++){
let file = e.target.files[i];
let blob = window.URL.createObjectURL(file);
createImageHTML(blob);
}}else{
document.getElementById('item-image').value = "";
}
});
}
});
画像投稿のビューはこのような感じです。
(省略)
<%= form_with model: @item, url:items_path, local: true do |f| %>
(省略)
<div class="img-upload">
<div class="weight-bold-text">
出品画像
<span class="indispensable">必須</span>
</div>
<div class="click-upload">
<div id="image-list"></div>
<p>
クリックしてファイルをアップロード(最大4枚まで)
</p>
<%= f.file_field :images, name: 'item[images][]', id:"item-image", multiple: true %>
</div>
</div>
(省略)
<% end %>
###完成形
なんとか、自分が思っていたとおりの実装が実現でき、とても感動しました。
もっと勉強して、レベルアップしていきたいと思います。
プログラミングの勉強はとても楽しいです。