首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用symfony3.x正确显示多个CollectionType字段

如何使用symfony3.x正确显示多个CollectionType字段
EN

Stack Overflow用户
提问于 2017-08-17 17:51:31
回答 1查看 2.6K关注 0票数 0

你好,我正在尝试建模一个使用几个不同集合的实体。我尝试了https://github.com/ninsuo/symfony-collection项目,它提供了一系列有用的选项。我所看到的最接近的例子是集合集合( Collection of Collection),其中一个实体拥有多个相同子EntityType的集合。我试图通过几个不同的子EntityTypes集合来实现相同的行为。

我的实体面临的问题是,当我只在其中放置一个集合时,代码工作正常,但是当我添加另一个子实体的第二个集合并发送我的表单时,我的控制器代码最终会删除其他集合的元素。我把范围缩小到视野上,因此我为什么要问那个特定的项目。

我目前正在使用Symfony 3.x,并且能够按照列出的示例一直到只使用一个集合才能很好地工作,我能够添加、删除和更新。

我的控制器代码:

代码语言:javascript
复制
namespace SigavFileBundle\Form;

use Ivory\CKEditorBundle\Form\Type\CKEditorType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use SigavFileBundle\Entity\BookingAccommodation;
use SigavFileBundle\Entity\BookingIncludes;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

class BookingType extends AbstractType
{
    /**
    * {@inheritdoc}
    */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('flights', CollectionType::class, 
                array(
                    'entry_type' => FlightDataType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__flights-collection__',
                    'attr'         => [
                        'class' => "flights-collection",
                    ],
                )
            )
            ->add('accommodations', CollectionType::class, 
                array(
                    'entry_type' => BookingAccommodationType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__accomm-collection__',
                    'attr'         => [
                        'class' => "accomm-collection",
                    ],
                )
            )
            ->add('cars', CollectionType::class, 
                array(
                    'entry_type' => BookingCarType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__cars-collection__',
                    'attr'         => [
                        'class' => "cars-collection",
                    ],
                )
            )
            ->add('transfers', CollectionType::class, 
                array(
                    'entry_type' => BookingTransferType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__transfers-collection__',
                    'attr'         => [
                        'class' => "transfers-collection",
                    ],
                )
            )
            ->add('excursions', CollectionType::class, 
                array(
                    'entry_type' => BookingExcursionType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__exc-collection__',
                    'attr'         => [
                        'class' => "exc-collection",
                    ],
                )
            )
            ->add('includes', CollectionType::class, 
                array(
                    'entry_type' => BookingIncludesType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__inc-collection__',
                    'attr'         => [
                        'class' => "inc-collection",
                    ],
                )
            )
            ->add('customActivities', CollectionType::class, 
                array(
                    'entry_type' => BookingCustomActivityType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__act-collection__',
                    'attr'         => [
                        'class' => "act-collection",
                    ],
                )
            )
            ->add('guides', CollectionType::class, 
                array(
                    'entry_type' => BookingGuideType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__guides-collection__',
                    'attr'         => [
                        'class' => "guides-collection",
                    ],
                )
            )
            ->add('commentaries', CollectionType::class, 
                array(
                    'entry_type' => BookingCommentariesType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                    'prototype'    => true,
                    'required'     => false,
                    'by_reference' => true,
                    'delete_empty' => true,
                    'prototype_name' => '__comm-collection__',
                    'attr'         => [
                        'class' => "comm-collection",
                    ],
                )
            )
        ;
    }

    /**
    * {@inheritdoc}
    */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'SigavFileBundle\Entity\Booking'
        ));
    }

    /**
    * {@inheritdoc}
    */
    public function getBlockPrefix()
    {
        return 'sigavfilebundle_booking';
    }
}

如您所见,多个不同类型的集合。接下来,这是其中两个只有BookingAccommodationTypeBookingCarType的代码

BookingAccommodationType:

代码语言:javascript
复制
namespace SigavFileBundle\Form;

use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use SigavGeneralBundle\Controller\MealPlanController;
use SigavGeneralBundle\Entity\Hotel;
use SigavGeneralBundle\Entity\RoomType;
use SigavGeneralBundle\SigavGeneralBundle;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;

class BookingAccommodationType extends AbstractType
{
    /**
    * {@inheritdoc}
    */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        ...
        // Attributes go here
        ...
    }
    
    /**
    * {@inheritdoc}
    */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'SigavFileBundle\Entity\BookingAccommodation'
        ));
    }

    /**
    * {@inheritdoc}
    */
    public function getBlockPrefix()
    {
        return 'sigavfilebundle_bookingaccommodation';
    }
}

BookingCarType:

代码语言:javascript
复制
namespace SigavFileBundle\Form;

use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TimeType;

class BookingCarType extends AbstractType
{
    /**
    * {@inheritdoc}
    */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        ...
        // Attributes go here
        ...
    }
    
    /**
    * {@inheritdoc}
    */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'SigavFileBundle\Entity\BookingCar'
        ));
    }

    /**
    * {@inheritdoc}
    */
    public function getBlockPrefix()
    {
        return 'sigavfilebundle_bookingcar';
    }
}

所有与视图相关的代码如下。

main_view.html.twig:

代码语言:javascript
复制
<!-- A lot of HTML code before //-->
{%
    form_theme form.accommodations
    'jquery.collection.html.twig'
    'booking/bookingAccommodations.html.twig'
%}

{{ form( form.accommodations) }}

<!-- A lot of HTML code between //-->

{%
form_theme form.cars
'jquery.collection.html.twig'
'booking/bookingCars.html.twig'
%}
{{ form( form.cars) }}

<!-- A lot of HTML code after //-->

<script>
    function initCollectionHolders( $id, $form_id )
    {
        $($id).collection({
            name_prefix:  $form_id,
            add_at_the_end: true,
            allow_add: 1,
            allow_duplicate: 1,
            allow_remove: 1,
            duplicate: '<a href="#"><span class="pe-7s-copy"></span></a>',
            add: '<a href="#"><span class="pe-7s-plus"></span></a>',
            remove: '<a href="#"><span class="pe-7s-close-circle"></span></a>'
        });
    }

    initCollectionHolders('.accomm-collection', '{{ form.accommodations.vars.full_name }}');
    initCollectionHolders('.cars-collection', '{{ form.cars.vars.full_name }}');
<script>

bookingCars.html.twig:

代码语言:javascript
复制
{% block sigavfilebundle_bookingcar_label %}{% endblock %}

{% block sigavfilebundle_bookingcar_widget %}

    {# HERE GOES THE ENTIRE FORM LAYOUT #} 

{% endblock %} 

bookingAccommodations.html.twig:

代码语言:javascript
复制
{% block sigavfilebundle_bookingaccommodation_label %}{% endblock %}

{% block sigavfilebundle_bookingaccommodation_widget %}

{# HERE GOES THE ENTIRE FORM LAYOUT #}

{% endblock %}

jquery.collection.html.twig:

代码语言:javascript
复制
{% block collection_widget %}
    {% spaceless %}
        {% if prototype is defined %}
            {% set attr = attr|merge({'data-prototype': form_row(prototype)}) %}
            {% set attr = attr|merge({'data-prototype-name': prototype.vars.name}) %}
        {% endif %}
        {% set attr = attr|merge({'data-allow-add': allow_add ? 1 : 0}) %}
        {% set attr = attr|merge({'data-allow-remove': allow_delete ? 1 : 0 }) %}
        {% set attr = attr|merge({'data-name-prefix': full_name}) %}
        {{ block('form_widget') }}
    {% endspaceless %}
{% endblock collection_widget %}

首先,我想知道symfony-collection库是否可以在具有一个实体和多个不同子类型集合的环境中使用

提前谢谢..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-23 05:12:46

跟随关于GitHub的探讨

name_prefix选项仅用于嵌套集合,它将有助于使用原型生成新条目,而不会在两个或多个集合之间发生冲突。

您正在寻找的是prefix选项,用于前缀由symfony-集合插件生成的所有选择器。在您的示例中,前缀对于所有集合都是相同的,因此单击一个或另一个按钮将触发对同一集合的操作。

如果希望在同一页面上创建多个集合,则需要更改集合前缀,以便插件能够为正确的集合触发正确的操作。

例如:

代码语言:javascript
复制
 $('.collectionA').collection({
    'prefix': 'first-collection'
 });

 $('.collectionB').collection({
    'prefix': 'second-collection'
 });

然后,如果您想编辑那些集合表单主题,您将需要替换集合-通过第一个集合添加-添加在您的添加按钮为exmaple。

代码语言:javascript
复制
<a href="#" class="first-collection-add btn btn-default">
    <span class="glyphicon glyphicon-plus-sign"></span>
</a>

有关正在运行的示例,请参见这个演示

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45741945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档