【问题标题】:Conditionally hide some embedded forms fields (collections) in Symfony在 Symfony 中有条件地隐藏一些嵌入的表单字段(集合)
【发布时间】:2018-11-13 21:24:40
【问题描述】:

我正在使用 Symfony 3.4。

我有国家和问题实体。 然后我有一个与国家和问题相关的答案实体。

在问题中,我定义了预期的答案类型(布尔值、字符串等)。

为了在答案实体中捕捉到这一点,我有几个字段与我定义的几种字段类型相匹配。

我想为给定国家/地区显示一个表格,以便编辑与不同问题对应的答案。

为了做到这一点,我正在使用国家/地区表单中的 collectionType。

但我的两个问题是:

  • 如何在嵌入式表单中显示问题本身
  • 如何在每个答案中隐藏不需要的字段(不是与问题对应的类型)。

当必须处理给定国家的所有问题/答案时,处理一个问题似乎很简单。

这是我的代码:

国家实体

    <?php

namespace cwt\psmdbBundle\Entity;

use APY\DataGridBundle\Grid\Mapping as GRID;
use Doctrine\ORM\Mapping as ORM;

/**
 * countries
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="cwt\psmdbBundle\Entity\Repository\countriesRepository")
 */
class countries
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=100)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="cwt\psmdbBundle\Entity\CcdbServicesAnswers", mappedBy="country", cascade={"persist", "remove"})
     */
    private $ccdbServicesAnswers;

问题实体:

    <?php

namespace cwt\psmdbBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use APY\DataGridBundle\Grid\Mapping as GRID;

/**
 * CcdbServicesQuestions
 *
 * @ORM\Table(name="ccdb_services_questions")
 * @ORM\Entity(repositoryClass="cwt\psmdbBundle\Repository\CcdbServicesQuestionsRepository")
 */
class CcdbServicesQuestions
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="question", type="string", length=255)
     */
    private $question;

    /**
     * @ORM\ManyToOne(targetEntity="cwt\psmdbBundle\Entity\CcdbServicesCategories")
     * @ORM\JoinColumn(nullable=false)
     * @GRID\Column(field="category.name", title="Category")
     */
    private $category;

    /**
     * @ORM\ManyToOne(targetEntity="cwt\psmdbBundle\Entity\FieldTypes")
     * @ORM\JoinColumn(nullable=false)
     * @GRID\Column(field="fieldType.name", title="Field Type")
     */
    private $fieldType;

    /**
     * @ORM\OneToMany(targetEntity="cwt\psmdbBundle\Entity\CcdbServicesAnswers", mappedBy="question", cascade={"persist", "remove"})
     */
    private $ccdbServicesAnswers;

回答实体:

    <?php

namespace cwt\psmdbBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * CcdbServicesAnswers
 *
 * @ORM\Table(name="ccdb_services_answers")
 * @ORM\Entity(repositoryClass="cwt\psmdbBundle\Repository\CcdbServicesAnswersRepository")
 */
class CcdbServicesAnswers
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string|null
     *
     * @ORM\Column(name="stringField", type="string", length=255, nullable=true)
     */
    private $stringField;

    /**
     * @var string|null
     *
     * @ORM\Column(name="textField", type="text", nullable=true)
     */
    private $textField;

    /**
     * @var bool|null
     *
     * @ORM\Column(name="booleanField", type="boolean", nullable=true)
     */
    private $booleanField;

    /**
     * @var int|null
     *
     * @ORM\Column(name="integerField", type="integer", nullable=true)
     */
    private $integerField;

    /**
     * @var float|null
     *
     * @ORM\Column(name="floatField", type="float", nullable=true)
     */
    private $floatField;

    /**
     * @var float|null
     *
     * @ORM\Column(name="percentageField", type="float", nullable=true)
     */
    private $percentageField;

    /**
     * @var string|null
     *
     * @ORM\Column(name="comment", type="string", length=255, nullable=true)
     */
    private $comment;

    /**
     * @ORM\ManyToOne(targetEntity="countries", inversedBy="ccdbServicesAnswers")
     * @ORM\JoinColumn(nullable=false)
     */
    private $country;

    /**
     * @ORM\ManyToOne(targetEntity="cwt\psmdbBundle\Entity\CcdbServicesQuestions", inversedBy="ccdbServicesAnswers")
     * @ORM\JoinColumn(nullable=false)
     */
    private $question;

这是我的国家/地区表格:

<?php

namespace cwt\psmdbBundle\Form;

use cwt\psmdbBundle\Entity\countries;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

class countriesCCDBServicesAnswersType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('ccdbServicesAnswers', CollectionType::class, array(
                'entry_type' => CcdbServicesAnswersType::class,
                'entry_options' => array('label' => false),
            ))
        ;

    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'cwt\psmdbBundle\Entity\countries'
        ));
    }

    /**
     * @return string
     */
    public function getBlockPrefix()
    {
        return 'cwt_psmdbbundle_countries';
    }
}

这是我的回答表格:

<?php

namespace cwt\psmdbBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
//use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class CcdbServicesAnswersType extends AbstractType
{
        /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('stringField')
            ->add('textField')
            ->add('booleanField')
            ->add('integerField')
            ->add('floatField')
            ->add('percentageField')
            ->add('comment')
//            ->add('country')
//            ->add('question')
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'cwt\psmdbBundle\Entity\CcdbServicesAnswers'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'cwt_psmdbbundle_ccdbservicesanswers';
    }
}

现在非常简单的控制器(我尝试访问表单字段,但我不知道从那里做什么):

    /**
     * Show answers for a given country.
     * @Route("/countries/{countryID}/edit", name="editCountryCcdbServicesAnswers", methods={"GET"})
     * @Security("has_role('ROLE_USER')")
     *
     */
    public function editCountriesCcdbServicesAnswers($countryID)
    {


//        // Get categories
        $em = $this->getDoctrine()->getManager();
        $categories = $em->getRepository('psmdbBundle:CcdbServicesCategories')->findAll();

        // $questions = $em->getRepository('psmdbBundle:CcdbServicesQuestions')->findAll();

        // Get all answers for this country
        $country = $em->getRepository('psmdbBundle:countries')->find($countryID);

        $form = $this->createCountryEditForm($country);

        foreach ($form as $field) {

            $fieldClass = get_class($field);

            if(get_class($field)=='Symfony\Component\Form\Form') {
                foreach ($field as $answerForm) {

                    foreach ($answerForm as $answerField) {

                    }

                }
            }

        }



        return $this->render('psmdbBundle:ccdb_services_answers:edit_country.html.twig', array(
            'categories' => $categories,
            'form' => $form->createView(),
            'entity' => $country,
//            'delete_form' => $deleteForm->createView(),
            'show' => 'ccdbservicesanswers_show',
            'cancel' => 'ccdbservicesanswers_show',
            'title' => 'CCDB Services',
        ));

    }

这是模板(非常没用,因为它显示每个答案的所有字段并且不显示问题......):

{% extends 'psmdbBundle:templates:edit.html.twig' %}

    {% block form_body -%}
        <div class="col-lg-5">

            {{ form(form) }}

        </div>
    {% endblock form_body %}

我正在考虑的一个解决方案是将问题字段添加到我的答案表单中,以便能够在表单主题中使用它们。但我不知道这是否是最好的方法,我担心性能。

另一种解决方案是在显示视图中使用 ajax 调用,以便在单击特定问题的“编辑”时即时构建表单,但我不相信用户体验!

有关信息,有 100 多个问题。

【问题讨论】:

    标签: symfony symfony-forms


    【解决方案1】:

    我找到了解决这两个问题的方法。

    为了显示问题文本,我只需将其添加到表单(禁用),然后设置样式,使其看起来像文本而不是输入。

    然后,为了只显示我需要的答案字段,我使用了表单事件,如下所示。我从问题中检索 fieldType 并有条件地添加必填字段。

    这是我的最终表格:

    <?php
    
    namespace cwt\psmdbBundle\Form;
    
    use FOS\CKEditorBundle\Form\Type\CKEditorType;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\Type\PercentType;
    use Symfony\Component\Form\Extension\Core\Type\TextareaType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\Form\FormEvent;
    use Symfony\Component\Form\FormEvents;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    //use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use cwt\psmdbBundle\Form\GpscSwitchType;
    
    class CcdbServicesAnswersType extends AbstractType
    {
            /**
         * @param FormBuilderInterface $builder
         * @param array $options
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
    
                ->add('question', textType::class, array(
                        'disabled' => true,
                        'label'     => false,
                        'attr' => array('class' => 'ccdb-form-question'),
                    )
                );
            $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
                $answer = $event->getData();
                $question = $answer->getQuestion();
                $fieldType = $question->getFieldType()->getName();
                $form = $event->getForm();
    
    
                switch ($fieldType) {
                    case 'boolean':
                        $form->add('booleanField', GpscSwitchType::class, array(
                            'label' => false,
                            'horizontal_label_class' => 'col-lg-12',
                            'horizontal_input_wrapper_class' => 'col-lg-3',
                            'attr' => array('class' => 'ccdb-form-answer boolean-type'),
                            'required'  => false,
                        ));
                        break;
                    case 'string':
                        $form->add('stringField', textAreaType::class, array(
                            'label' => false,
                            'horizontal_label_class' => 'col-lg-12',
                            'horizontal_input_wrapper_class' => 'col-lg-12',
                            'attr' => array('class' => 'ccdb-form-answer'),
                            'required'  => false,
                            ));
                        break;
                    case 'integer':
                        $form->add('integerField', null, array(
                            'label' => false,
                            'horizontal_label_class' => 'col-lg-12',
                            'horizontal_input_wrapper_class' => 'col-lg-2',
                            'attr' => array('class' => 'ccdb-form-answer'),
                            'required'  => false,
                            ));
                        break;
                    case 'percentage':
                        $form->add('percentageField', percentType::class, array(
                            'label' => false,
                            'scale' => 2,
                            'horizontal_label_class' => 'col-lg-12',
                            'horizontal_input_wrapper_class' => 'col-lg-2',
                            'attr' => array('class' => 'ccdb-form-answer'),
                            'required'  => false,
                            ));
                        break;
                    case 'float':
                        $form->add('floatField', null, array(
                            'label' => false,
                            'horizontal_label_class' => 'col-lg-12',
                            'horizontal_input_wrapper_class' => 'col-lg-2',
                            'attr' => array('class' => 'ccdb-form-answer'),
                            'required'  => false,
                            ));
                        break;
                    case 'text':
                        $form->add('textField', CKEditorType::class, array(
                            'label' => false,
                            'horizontal_label_class' => 'col-lg-12',
                            'horizontal_input_wrapper_class' => 'col-lg-12',
                            'attr' => array('class' => 'ccdb-form-answer'),
                            'required'  => false,
                            ));
                        break;
                }
    
                $form->add('comment', textAreaType::class, array(
                    'label' => 'Comment:',
                    'horizontal_label_class' => 'col-lg-12',
                    'horizontal_input_wrapper_class' => 'col-lg-12',
                    'attr' => array('class' => 'ccdb-form-answer ccdb-form-comment'),
                    'required'  => false,
                    ));
    
    
            });
        }
    
        /**
         * @param OptionsResolver $resolver
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'cwt\psmdbBundle\Entity\CcdbServicesAnswers'
            ));
        }
    
        /**
         * @return string
         */
        public function getName()
        {
            return 'cwt_psmdbbundle_ccdbservicesanswers';
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-06
      • 2012-12-22
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-15
      相关资源
      最近更新 更多