Laravel Blade循环中Dropzone失效:提示已绑定错误
问题:Laravel Blade循环生成的模态框中Dropzone报错
Dropzone already attached 在Laravel Blade里遍历购物车商品,为每个商品生成一个用于上传商品图片的模态框,但打开模态框时Dropzone无法正常工作,控制台报错:
dropzone.js:1 Uncaught Error: Dropzone already attached.
模态框代码(front::products.partials.add-multiple-photo视图内容)
<div class="modal fade" id="productmultiplephoto-{{$product->pivot->id}}" role="dialog" aria-labelledby="productmultiplephoto" aria-hidden="true"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header pb-0"> <h5 class="modal-title" id="price-changes-modal-label"></h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="__img"> <div class="form-group"> <input type="hidden" name="original_name[]" id="product-photo"> <input name="product_id" value="{{$product->id}}" type="hidden" id="product_id" > <input name="product_pivot" value="{{$product->pivot->id}}" type="hidden" id="product_pivot" > <input name="cartproduct_id" type="hidden" id="cartproduct_id"value="{{$product->pivot->id}}" > <label for="photog">upload</label> <input type="hidden" name="original_name[]" id="product-photo"> <div id="photog" class="dropzone" ></div> </div> </div> </div> </div> </div>
脚本代码
<script> Dropzone.autoDiscover = false; var photosGallery = [] var drop = new Dropzone('#photog', { addRemoveLinks: true, url: "{{ route('front.photouser.upload') }}", type:"POST", sending: function(file, xhr, formData){ formData.append("_token","{{csrf_token()}}") formData.append("product_id", document.getElementById('product_id').value); formData.append("product_pivot", document.getElementById('product_pivot').value); formData.append("cartproduct_id", document.getElementById('cartproduct_id').value); }, success: function(file, response){ photosGallery.push(response.original_name) if (response['level'] == 1) { $('.level1_message').html(response['message']); } } }); productGallery = function(){ document.getElementById('product-photo').value = photosGallery } </script>
模态框触发按钮代码
@foreach($cart->products as $product) <button type="button" data-toggle="modal" data-target="#productmultiplephoto-{{$product->pivot->id}}" class="btn-primary-multiple btn-primary-cm btn-with-icon"> <i class="mdi mdi-plus-box-multiple"></i> upload </button> @endforeach
模态框引入代码
@include('front::products.partials.add-multiple-photo')
解决方案
问题根源
- 所有模态框内的Dropzone容器、隐藏输入框都使用了重复的
id(比如photog、product_id),DOM中id必须唯一,重复id会导致元素选择混乱。 - 脚本提前全局初始化
#photog,但页面中存在多个相同id的元素,Dropzone尝试重复绑定到同一选择器,触发"already attached"错误。
修复步骤
1. 给模态框内元素添加唯一标识
修改模态框视图,将所有id替换为包含{{$product->pivot->id}}的唯一值,同时移除重复的隐藏输入框:
<div class="modal fade" id="productmultiplephoto-{{$product->pivot->id}}" role="dialog" aria-labelledby="productmultiplephoto" aria-hidden="true"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header pb-0"> <h5 class="modal-title" id="price-changes-modal-label"></h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="__img"> <div class="form-group"> <input type="hidden" name="original_name[]" id="product-photo-{{$product->pivot->id}}"> <input name="product_id" value="{{$product->id}}" type="hidden" id="product_id-{{$product->pivot->id}}" > <input name="product_pivot" value="{{$product->pivot->id}}" type="hidden" id="product_pivot-{{$product->pivot->id}}" > <input name="cartproduct_id" type="hidden" id="cartproduct_id-{{$product->pivot->id}}" value="{{$product->pivot->id}}" > <label for="photog-{{$product->pivot->id}}">upload</label> <div id="photog-{{$product->pivot->id}}" class="dropzone" ></div> </div> </div> </div> </div> </div>
2. 动态初始化/销毁Dropzone实例
改为监听模态框的显示/关闭事件,仅对当前打开的模态框初始化Dropzone,关闭时销毁实例,避免重复绑定:
<script> Dropzone.autoDiscover = false; // 存储每个模态框对应的Dropzone实例和图片数组 const dropzoneInstances = {}; // 模态框显示时初始化Dropzone $('.modal[id^="productmultiplephoto-"]').on('show.bs.modal', function() { const modalId = $(this).attr('id'); const pivotId = modalId.replace('productmultiplephoto-', ''); const dropzoneSelector = `#photog-${pivotId}`; // 避免重复初始化 if (dropzoneInstances[pivotId]) return; const photosGallery = []; const drop = new Dropzone(dropzoneSelector, { addRemoveLinks: true, url: "{{ route('front.photouser.upload') }}", type: "POST", sending: function(file, xhr, formData){ formData.append("_token","{{csrf_token()}}"); formData.append("product_id", document.getElementById(`product_id-${pivotId}`).value); formData.append("product_pivot", document.getElementById(`product_pivot-${pivotId}`).value); formData.append("cartproduct_id", document.getElementById(`cartproduct_id-${pivotId}`).value); }, success: function(file, response){ photosGallery.push(response.original_name); if (response['level'] == 1) { $('.level1_message').html(response['message']); } // 更新当前模态框的隐藏输入框 document.getElementById(`product-photo-${pivotId}`).value = photosGallery; }, removedfile: function(file) { // 移除图片时同步更新数组 const index = photosGallery.indexOf(file.original_name); if (index > -1) { photosGallery.splice(index, 1); document.getElementById(`product-photo-${pivotId}`).value = photosGallery; } file.previewElement.remove(); } }); dropzoneInstances[pivotId] = { drop, photosGallery }; }); // 模态框关闭时销毁Dropzone实例 $('.modal[id^="productmultiplephoto-"]').on('hidden.bs.modal', function() { const modalId = $(this).attr('id'); const pivotId = modalId.replace('productmultiplephoto-', ''); if (dropzoneInstances[pivotId]) { dropzoneInstances[pivotId].drop.destroy(); delete dropzoneInstances[pivotId]; } }); </script>
内容的提问来源于stack exchange,提问作者user14500330
相关产品推荐
相关产品推荐

