枚数制限の記事無くない?
複数画像アップロード方法は過去の記事で記載しているのですが(良かったら見てください。こちら)、例えば画像を複数選択したいけど、5枚までしか登録できない様にしたいんだよなー...という時ないですか?
私も色々記事をあさったのですが中々良い記事が見つかりませんでした。めちゃくちゃ需要ありそうやのに。
なので、今回その方法をお伝えします!!
あくまで一個人の方法なのでもっと良い方法があれば教えてください!!
##HTMLの用意
= form_with(model:@item, locale: true , id: 'new_item') do |f|
.item-image-container
= f.label :"出品画像"
%span.form-require 必須
%p.item-image-container__lead
最大5枚までアップロードできます
.item-image-container__unit
= f.fields_for :item_images do |i|
%ul
.item-image-container__unit--guide
%label(for="image-label")
= i.file_field :image, multiple: true, class: 'image-upload-dropfile-hidden', id:"image-label",type: 'file', name: "item_images[image][]"
%div.image-upload-dropfile-entire
.have-image
= icon('fas','camera')
%p#d-d-delete ドラッグ&ドロップ
%p#click-delete またはクリックしてファイルをアップロード
まず何でもよいのですが、適当にこの様なViewを作ってください。
プレビューの際、画像がアップロードされるとulタグの下にJavaScript側で用意したhtmlを挿入していく形で進めていきます。
##JavaScript,jQueryの用意
$(function(){
//DataTransferオブジェクトで、データを格納する箱を作る
var dataBox = new DataTransfer();
//querySelectorでfile_fieldを取得
var file_field = document.querySelector('input[type=file]')
//fileが選択された時に発火するイベント
$('#image-label').change(function(){
//選択したfileのオブジェクトをpropで取得
var files = $('input[type="file"]').prop('files')[0];
$.each(this.files, function(i, file){
//FileReaderのreadAsDataURLで指定したFileオブジェクトを読み込む
var fileReader = new FileReader();
//DataTransferオブジェクトに対して、fileを追加
dataBox.items.add(file)
//DataTransferオブジェクトに入ったfile一覧をfile_fieldの中に代入
file_field.files = dataBox.files
//Fileオブジェクトを読み込む
fileReader.readAsDataURL(file);
//読み込みが完了すると、srcにfileのURLを格納
fileReader.onloadend = function() {
var src = fileReader.result
var html = `<li class="item-image-container__unit--preview" >
<div class="item-image-container__unit--caption">
<img src="${src}">
</div>
<div class="image-option">
<div class="image-option__list">
<div class="image-option__list--tag">編集</div>
</div>
<div class="image-option__list">
<a class="image-option__list--tag">削除</a>
</div>
</div>
</li>`
//ulタグの下にhtmlをappendしています。
$(html).appendTo(".item-image-container__unit ul").trigger("build");
};
//DataTransfer構造のデバッグ
console.log(dataBox);
});
});
});
複数アップロードでプレビューをする際に1つ以上の画像を保持し、データを格納しておく為にDataTransferクラスを使用することが画像枚数制限をかける上で大変重要になります。
他はコメントアウトしているので読んで理解していってもらえるとありがたいです。
if(dataBox.items.length > 4){
return false;
}
こちらが枚数制限をかける記述です。
意外と単純でしたね。
console.log(dataBox);の下にこの記述を追加してください。
ではなぜこの様な記述をしたのかを解説していきます。
引数にDataTransferオブジェクトを入れたconsole.logでデバッグを行なった結果この様な構造がコンソール上で取得できました。
lengthに注目してください。データを格納する配列に制限をかけてやれば良いのです。
つまりDataTransferのlengthを取得してそれに対して関係演算子を組み込めば、好きな枚数で制限をかけることが可能になります。
これでもし6枚選択してしまってもちゃんと配列には5枚しか登録されません。
当然DBにも5枚で登録されます。
文字がおかしくなるのはお許しください。
今回の理論を使えば文字を消すことだってできるはずです。