为什么symfony只在这里渲染一个嵌套的表单集合元素?

时间:2014-06-25 19:44:44

标签: php forms symfony collections

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

我有一个应用程序,我正在为我的人力资源部门工作,这将用于执行员工年度评估。他们按照要求的方式,有按主题(商业意识,技能等)分组的子弹点页面,每个项目符号点由评论者分配一个分数。公司的每个职位都有相同的三页子弹点,但每个部门可以选择为整个部门或每个职位增加更多。

我有我的实体设计和正常工作。

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

我已经用var_dump检查了构建器,而EvaluationType(外部表单)显示了在表单中注册的页面,如果我var_dump是EvaluationPage对象,它会显示注册到对象的项目符号,但是当表单呈现,只有最后一个子弹点呈现。没有任何其他页面显示任何其他点,只添加了最后一个。我已经检查过并重新检查了,我确定它很简单,但我无法找到问题。

以下是我的代码段:

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));
             }
         }

    }    

}

评估页面(内部表格):     

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和类似的ops。

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

因此,当页面呈现时,显示的唯一要点是“对影响组织,行业和业务环境的问题有广泛而深刻的理解。”以及它的文本框。表单的其余部分显示正常,但只有一个项目符号存在。

我仍然对Symfony有点新鲜,所以如果我以奇怪的方式做某事或做了些蠢事,那可能就是原因。

我错过了什么?

1 个答案:

答案 0 :(得分:1)

答案

这个问题是双重问题,原因是处理集合字段类型的方式,以及我的事件订阅者的错误。

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

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

那是由我的活动订阅者引起的。这是我以前试图让这个工作的方式的遗物,并忘了删除它。它正在循环锁定条目并重新分配&#34;页面_&#34;带有每次迭代信息的文本字段,因为我忘了将迭代器附加到字段的末尾。 (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,
                        )
                    ));
            }

        }

    }

}