Symfony CollectionType仅保存最后新增项的技术求助
Symfony CollectionType 新增子表单仅最后一项保存问题
在自定义表单类型中使用Symfony CollectionType时,添加并填写两个新子表单提交后,仅最后一项被保存,已耗时四小时排查无果。
按官方教程使用jQuery结合CollectionType提供的prototype实现子表单添加功能,调试发现提交数据正确,但表单对象hydrate时所有新增项均被替换为最后一项。
使用环境:PHP 8.1、Symfony 5.4,已准备可复现该问题的仓库。
表单类型代码
class CustomType extends AbstractType { public function buildForm(...) { $builder->add( 'collection', CollectionType::class, [ 'required' => false, 'entry_type' => CustomItemType::class, 'allow_add' => true, 'allow_delete' => true, 'prototype' => true, 'label' => 'Some label', 'by_reference' => false, 'error_bubbling' => false, 'entry_options' => [ 'empty_data' => new CustomItem(), 'by_reference' => false ] ] ); } public function configureOptions(...) { $resolver->setDefaults(['data_class' => CustomContainer::class]); } }
子表单添加JS代码
function addItem(e) { e.preventDefault(); var collectionSelector = $(this).data('collection-selector'); var list = $(collectionSelector); var counter = list.data('widget-counter'); var newWidget = list.data('prototype'); var newHtmlElem = newWidget.replace(/__name__/g, counter); var newElem = $(newHtmlElem); newElem.on('click', e.data.removeButtonClass, {itemContainerClass: e.data.itemContainerClass}, removeItem); counter++; list.data('widget-counter', counter); var accordianContainer = $(collectionSelector + ' ' + e.data.collapse); newElem.appendTo(accordianContainer); } $(document).ready(function () { $('body').tooltip({selector: '.custom-tooltip'}); $('.add-custom-item-btn').click({removeButtonClass: '.remove-custom-item-btn', itemContainerClass: '.custom-item-item', collapse: '#custom-item-accordion'}, addItem); $('.remove-custom-item-btn').click({itemContainerClass: '.custom-item-item'}, removeItem); });
Twig模板代码片段
{% macro printItem(custom_item, index) %} <div class="panel panel-default custom-item-item"> <div class="panel-heading" role="tab" id="custom-item-heading-{{ index }}"> <h4 class="panel-title"> <a role="button" data-toggle="collapse" data-parent="#custom-item-accordion" href="#custom-item-collapse-{{ index }}" class="collapsed" > Custom Item </a> </h4> </div> <div id="custom-item-collapse-{{ index }}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="custom-item-heading-{{ index }}" aria-expanded="false" > <div class="panel-body"> {{ form_row(custom_item) }} <button type="button" class="remove-custom-item-btn btn btn-primary btn-sm"> <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> </button> </div> </div> </div> {% endmacro %} {% import _self as formMacros %} <div class="row"> <div class="col-xs-12 form-group"> <button type="button" class="add-custom-item-btn btn btn-primary btn-sm" data-collection-selector="#custom-container-fields-list"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> </button> </div> <div id="custom-container-fields-list" data-prototype="{{ formMacros.printItem(form.collection.vars.prototype, '__name__') }}" data-widget-counter="{{ max(form.collection|keys) + 1 }}" > <div class="panel-group" id="custom-item-accordion" role="tablist" aria-multiselectable="true"> {% for index, custom_item in form.collection %} {{ formMacros.printItem(custom_item, index) }} {% endfor %} </div> </div> </div>
内容的提问来源于stack exchange,提问作者GatorGuy023
相关产品推荐
相关产品推荐

