【问题标题】:Why is symfony only rendering one nested form collection element here?为什么 symfony 在这里只渲染一个嵌套的表单集合元素?
【发布时间】:2014-08-16 12:31:16
【问题描述】:

编辑:我已经弄清楚了这个问题。下面的解释和我的解决方法。

我正在为我的人力资源部门开发一个应用程序,该应用程序将用于执行员工年度评估。按照他们的要求,有几页按主题(商业意识、技能等)分组的要点,每个要点都由审阅者分配一个分数。公司的每个职位都有相同的三页要点,但每个部门可以选择为整个部门或每个职位添加更多。

我的实体为此设计并正常工作。

我遇到的问题是我在渲染表单时遇到了一些问题。现在,出于测试目的,我只是使用 {{ form(evaluation) }} 呈现表单。它是用嵌套在集合中的表单构建的。

我已经用 var_dump 检查了构建器,EvaluationType(外部表单)显示了在表单中注册的页面,如果我 var_dump 评估页面对象,它会显示注册到该对象的项目符号,但是当表单渲染,只有最后一个项目符号点渲染。没有显示任何其他页面的其他点,只显示最后一个。我检查了又检查了,我确定这很简单,但我找不到问题。

这是我的代码 sn-ps:

EvaluationController(getModernEvaluationLocker 只使用虚拟数据:

namespace Company\PerformanceBundle\Controller;

use Company\PerformanceBundle\Entity\Noncommitable\EvaluationLocker;
use Company\PerformanceBundle\Form\Builders\EvaluationType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class EvaluationController extends Controller
{
    /**
     * @Route("/strive/evaluation", name="eval")
     * @Template("CompanyPerformanceBundle:Evaluation:Evaluation.html.twig")
     */
    function evaluationEntryAction()
    {

        $locker = $this->getModernEvaluationLocker();

        $em = $this->getDoctrine()->getManager();
        $form = $this->createForm(new EvaluationType($em, $locker));



        return array(
            'sidebarTitle' => 'Strive Evaluations Manager',
            'sidebar' => null,
            'function' => 'test',
            'title' => 'test',
            'evaluation' => $form->createView(),
        );
    }

    private function getModernEvaluationLocker()
    {
        $locker = new EvaluationLocker();

        $locker ->addPage('Brand Pillars and Core Values')
                    ->addBullet('Inspires a passion for the industry and ensures that the needs of all customers (internal and external) are met, benefitting both the customer and organization.')
                    ->addBullet('Completes work to high standards and continually looks for ways to improve performance.')
                    ->addBullet('Delivers remarkable customer service 100% of the time, each and everytime to both our internal and external customers.')
                ->addPage('Business Acumen')
                    ->addBullet('Clear understanding of The Company’s mission, initiatives and direction.')
                    ->addBullet('Has a broad and deep understanding of the issues that affect the organization, industry and the business environment.');

        return $locker;
    }  
}

EvaluationType(外部形式):

namespace Company\PerformanceBundle\Form\Builders;

use Doctrine\ORM\EntityManager;
use Company\PerformanceBundle\Entity\Noncommitable\EvaluationLocker;
use Company\PerformanceBundle\Entity\Noncommitable\EvaluationLockerPage;
use Company\PerformanceBundle\Form\EventListener\EvaluationPageSubscriber;
use Company\PerformanceBundle\Form\Fields\EvaluationPage;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class EvaluationType extends AbstractType {
    private $entityManager;
    private $evalLocker;

    public function __construct(EntityManager $em, EvaluationLocker $locker)
    {
        $this->entityManager = $em;
        $this->evalLocker = $locker;
    }

    public function getName() {

        return 'evaluation';

    }
    public function buildForm(FormBuilderInterface $builder, array $options) {

         $builder->addEventSubscriber(new EvaluationPageSubscriber($this->evalLocker));

         $builder
                ->add('employeeID', 'text', array(
                    'label' => 'Employee ID:',
                    'required' => true,
                    'trim' => true,
                    'error_bubbling' => true,
                    ))
                ->add('managerLogin', 'text', array(
                    'label' => 'Manager Login:',
                    'required' => true,
                    'trim' => true,
                    'error_bubbling' => true,
                    'mapped' => false,
                    ))
                ->add('managerPassword', 'password', array(
                    'label' => 'Manager Password:',
                    'required' => true,
                    'trim' => true,
                    'error_bubbling' => true,
                    'mapped' => false,
                    ))
                ->add('appraisalType', 'choice', array(
                    'choices' => array('0' => '90 Day', '1' => 'Annual'),
                    'required' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Appraisal Type:',
                    'error_bubbling' => true,
                ))
                ->add('pages', 'collection');

         for($i =0; $i<=$this->evalLocker->getPageCount(); $i++)
         {
             $page = ($i==0 ? $this->evalLocker->rewind() : $this->evalLocker->next());
             if ($page)
             {  
                $builder->get('pages')->add('page_' . $i, new EvaluationPage($page));
             }
         }

    }    

}

EvaluationPage(内部形式):

namespace Company\PerformanceBundle\Form\Fields;

use Company\PerformanceBundle\Entity\Noncommitable\EvaluationLockerPage;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class EvaluationPage extends AbstractType {

    private $page;

    public function __construct( EvaluationLockerPage $page)
    {
        $this->page = $page;
    }

    public function getName() {

        return 'evaluationPage';

    }

    public function buildForm(FormBuilderInterface $builder, array $options) 
    {

        $builder->add('bullets', 'collection');

        $i =0;
        foreach ($this->page as $bullet => $value)
        {
            if ($bullet)
            {   
                $builder->get('bullets') -> add('bullet_'.$i, 'text', array(
                    'label' => $bullet,
                    'data'  => $value,
                    'required' => true,
                    'trim' => true,
                    ));
            }

            $i++;    
        }
    }
}

EvaluationLocker 和 EvaluationLockerPage 是简单的对象,具有 ArrayAccess 和 Iterator 接口,以及一些简单的函数,例如 getPageCount 和类似的操作。

将EvaluationLocker 视为EvaluationLockerPage 数组的数组。每个 EvaluationLockerPage 条目都是一个键/值对,其中键是要点文本,值是分配给它的分数。

因此,当页面呈现时,显示的唯一要点是“对影响组织、行业和业务环境的问题有广泛而深入的了解”。连同它的文本框。表单的其余部分显示正常,但只有一个要点。

我对 Symfony 还是有点陌生​​,所以如果我做了一些奇怪的事情或做了一些愚蠢的事情,这可能就是原因。

我错过了什么?

【问题讨论】:

    标签: php forms symfony collections


    【解决方案1】:

    答案

    问题是双重的,由处理集合字段类型的方式以及我的事件订阅者中的错误引起的。

    symfony 引擎不会渲染集合条目,除非它们被分配了一个实际的值。由于这些文本框是空的,symfony 忽略了它们,期望通过 javascript 和原型将这些框添加到表单中。

    这导致表单行不显示。但是,请记住显示的是 ONE 行。

    这是由我的事件订阅者引起的。这是我以前试图让它工作的一种方式的遗物,但忘了删除它。它在更衣室条目上循环并重新分配一个“pages_”文本字段,其中包含每次迭代的信息,因为我忘记在字段末尾附加一个迭代器。 ( pages_1、pages_2 等)将迭代器添加到字段并消除 EvaluationType 文件中的 foreach 循环使所有字段都成功呈现。

    我在订阅者的字段分配中添加了一个数据分组属性来设置问题应该出现在哪个页面上,在隐藏的 div 中呈现项目符号点,然后使用 javascript 将 dom 节点移动到它们在通过循环访问页面 div

    document.getElementById('page' + pageNum + '_div').appendChild(
        document.querySelectorAll('[data-grouping="page' + pageNum + '"]').parentNode);
    

    其中 pageNum 是我当前正在构建的页码。

    有点笨拙的解决方法,但它有效,而且我的头发仍然完好。

    更新的事件订阅者:

    <?php
    
    namespace Company\PerformanceBundle\Form\EventListener;
    
    use Company\PerformanceBundle\Entity\Noncommitable\EvaluationLocker;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\Form\FormEvent;
    use Symfony\Component\Form\FormEvents;
    
    class EvaluationPageSubscriber implements EventSubscriberInterface{
    
        private $EvaluationLocker;
    
        public function __construct(EvaluationLocker $locker)
        {
            $this->EvaluationLocker = $locker;
        }
    
    
        public static function getSubscribedEvents() {
    
            return array(FormEvents::PRE_SET_DATA => 'preSetData');
    
        }
    
        public function preSetData(FormEvent $event)
        {
            $form = $event->getForm();
    
            list($i,$j) = array(0,0);
    
            foreach ( $this->EvaluationLocker as $contents )
            {
                $i++;
    
                foreach ($contents as $bullet => $value)
                {
                    $j++;
                    $form->add('page_' . $i . '-bullet_' . $j, 'text', array(
                        'label' => $bullet,
                        'trim' => true,
                        'data' => $value,
                        'attr' => array(
                            'data-grouping' => 'page' . $i,
                            )
                        ));
                }
    
            }
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      • 2021-10-08
      • 1970-01-01
      • 1970-01-01
      • 2019-06-16
      相关资源
      最近更新 更多