実現したいこと
現在、口コミサイトのようなものを作成しています。
そこで最大3枚まで画像を付けられるように設計しております。
編集画面にて画像を変更したいとなった場合、下記を実現したいと考えております。
①すでに最初の投稿で画像をアップロードしていた場合はそのプレビュー表示と削除ができる。
②①で既存画像を削除した場合は新しい画像がアップロードできる。
③既存画像が1枚のみだった場合、残り2枚画像をアップロードできる。
発生している問題・分からないこと
現在、上記実現したいことのうち①と②は実装できたのですが、③のみができておりません。
既存画像が1枚ある状態の時に、既存画像のプレビュー表示はされている。また削除及び追加もできる。
既存画像が1枚ある状態の時に、新しい画像のアップロードをしようとすると画像選択はできるがプレビュー表示ができない。
エラーを見ると、「preview-container」のindexが正しく取れていないようなので、色々コードを書き換えてみたりしたのですがわからずじまいです。
エラーメッセージ
error
1Uncaught TypeError: Cannot read properties of undefined (reading 'querySelector')
該当のソースコード
html.erb
1<!-- 画像アップロード --> 2 <div class="row justify-content-center"> 3 <div id="file_input_container" class="mb-4"> 4 <p>写真を追加する(最大3枚まで)</p> 5 <div class="d-flex justify-content-start"> 6 <% @review.images.each_with_index do |image, index| %> 7 <div class="file-input-wrapper" data-controller="edit-preview"> 8 <!-- 既存画像のプレビュー --> 9 <div class="preview-container" data-edit-preview-target="preview" data-index="<%= index %>" style="display: block;"> 10 <%= image_tag url_for(image), alt: "Uploaded Image", class: "img-thumbnail" %> 11 </div> 12 <%= form.check_box :existing_image_ids, { multiple: true, id: "delete_checkbox_#{index}", class: "d-none" }, image.id, nil %> 13 <button type="button" class="delete-btn" data-action="click->edit-preview#delete" 14 data-edit-preview-target="deleteBtn" data-index="<%= index %>" style="display: block;">×</button> 15 <input type="file" name="review[images][]" accept="image/*" class="form-control-file" 16 data-edit-preview-target="fileInput" data-action="change->edit-preview#initializeFileInput" 17 data-index="<%= index %>" style="display: none;"> 18 <div class="plus-icon" data-edit-preview-target="plusIcon" data-index="<%= index %>" style="display: none;">+</div> 19 </div> 20 <% end %> 21 22 <!-- 新規画像 --> 23 <% remaining_images = 3 - @review.images.size %> 24 <% if remaining_images > 0 %> 25 <% remaining_images.times do |i| %> 26 <div class="file-input-wrapper" data-controller="edit-preview"> 27 <input type="file" name="review[images][]" accept="image/*" class="form-control-file" 28 data-edit-preview-target="fileInput" data-action="change->edit-preview#initializeFileInput" 29 data-index="<%= @review.images.size + i %>"> 30 <div class="plus-icon" data-edit-preview-target="plusIcon">+</div> 31 <div class="preview-container" data-edit-preview-target="preview" data-index="<%= @review.images.size + i %>" style="display: none;"> 32 <img src="" alt="Preview"> 33 </div> 34 <button type="button" class="delete-btn" data-action="click->edit-preview#delete" 35 data-edit-preview-target="deleteBtn" data-index="<%= @review.images.size + i %>" style="display: none;">×</button> 36 </div> 37 <% end %> 38 <% end %> 39 </div> 40 </div> 41 </div>
controller.js
1initializeFileInput(event) { 2 const input = event.target; 3 const index = input.dataset.index; 4 const file = input.files[0]; 5 6 console.log("Input index:", index); 7 console.log("Preview Targets:", this.previewTargets); 8 9 console.log("Preview Targets:", this.previewTargets); 10 console.log("Total previewTargets length:", this.previewTargets.length); 11 12 const previewContainer = this.previewTargets[index]; 13 const plusIcon = this.plusIconTargets[index]; 14 const deleteBtn = this.deleteBtnTargets[index]; 15 16 if (file) { 17 // ファイルが選択された場合、プレビューを表示 18 const reader = new FileReader(); 19 reader.onload = (e) => { 20 const img = previewContainer.querySelector('img'); 21 img.src = e.target.result; 22 23 plusIcon.style.display = 'none'; 24 previewContainer.style.display = 'block'; 25 deleteBtn.style.display = 'block'; 26 }; 27 28 reader.readAsDataURL(file); 29 } 30} 31
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
現在はソースコードを既存画像がある場合に応じて新規画像のアップロードフォームを増減する形にしていますが、それを最初からフォームを3つ作りその中で既存画像がある場合とない場合にわけたりしたソースコードも試しましたが、結果は同じでした。
補足
特になし
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。