【问题标题】:Symfony2 Dynamic Groups of EntityType fields in formSymfony2 EntityType 字段的动态组在表单中
【发布时间】:2013-11-19 16:45:18
【问题描述】:

我正在尝试开发一种表格,让学生可以从多个小组中选择课程。定义如下:

  • 课程有名称/描述/小时数。
  • 课程属于小组,有名称/描述/时间限制(例如,您必须从该小组中选择 5 个学分,或者您最多只能从该小组中选择 10 个小时)
  • 课程组被组织成一个程序既定课程,可以有其他字段

所以我希望表格允许学生选择课程,但课程是按这些组组织的,并附有关于选择多少个的说明。学分部分将使用自定义验证规则进行验证。

这是我正在考虑的代码的一个想法(省略了很多命名空间/Doctrine 映射/等)。

实体有点像这样:

class Offering
{
    // has multiple CourseGroups
    private $groups;
}

class CourseGroup
{
    // which Offering it belongs to
    private $offering;
    private $name;
    private $maxHours;
}

class Course
{
    // which CourseGroup it belongs to
    private $group;
    private $name;
    private $hours;
}

// User submits an application with chosen courses from multiple groups
class Application
{
    // ...
    private $courses;
}

// Joins the Applications to Courses (N to N)
class ApplicationCourse
{
    // which Application
    private $application;
    // which Course
    private $course;
}

但我正在尝试弄清楚如何将其放入表单中。我不介意将表单绑定到一个数组并稍后将其排序以将其放入Application

class ApplicationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...other fields
        ;

        // Add the groups of courses to choose
        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) use ($offering) {
                $form = $event->getForm();

                // Here I would like to add 1 EntityType per Offering
                // The EntityType allows the user to select multiple Courses within that group
                $i = 0;
                foreach ($offering->groups as $group) {
                    // Maybe add the $group as a static block in the twig template here
                    // Ideally the form should show the group name/description

                    // I'll probably borrow from this class https://github.com/genemu/GenemuFormBundle/blob/master/Form/Core/Type/PlainType.php

                    // This adds a group of checkboxes to select a course from this group
                    $form->add('course_'.$i, 'entity', array(
                        'class' => 'Acme\DemoBundle\Entity\Course',
                        'property' => 'name',
                        'multiple' => true,
                        'expanded' => true,
                        'query_builder' => function(EntityRepository $er) use ($group) {
                            // imagine this ia a query that selects all courses in the $group
                            return $er->createGroupCoursesQueryBuilder($group);
                        },
                    );
                    $i++;
                }
            }
        );
    }

    public function getName()
    {
        return 'task';
    }
}

最后,我想要一个看起来像这样的表单:

科学:选择至少 4 个学分

  • [x] SCI100(2 小时)
  • [ ] SCI101(2 小时)
  • [ ] SCI102(2 小时)

数学:选择至少 4 个学分

  • [ ] MTH100(4 小时)
  • [x] MTH101(4 小时)

{组名}:{组描述}

  • [{selected?}] {COURSE NAME} {COURSE HOURS}

等等

这种方法行得通吗?有没有更好的方法让我不必将该表单绑定到一个数组,然后在验证后重新组装它?

【问题讨论】:

标签: php forms symfony


【解决方案1】:

看到这个答案Symfony 2 Forms entity Field Type grouping后,解决方法其实很简单

我刚刚自定义了表单的呈现。最好的部分是,我得到了 Symfony 表单的所有有用部分(数据绑定),但我可以完全自定义呈现。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('courses', 'entity', array(
            'class' => 'MyMainBundle:Course',
            'property' => 'name',
            'multiple' => true,
            'expanded' => true
        ))
        ->add('save', 'submit')
    ;
}

twig 模板中有一个很酷的技巧,可以自己渲染。我确实必须通过课程组。

诀窍是使用{% do form.courses.setRendered %}

{{ form_start(form) }}
    {{ form_errors(form) }}

    {% for group in academics.courseGroups %}
    <section>
        <h2>
            {{ group.name }}
        </h2>
        <p>{{ group.description }}</p>

        {% for course in group.courses %}
        <div class="form-group">
            <div class="course">
                <div class="checkbox">
                    <label for="my_mainbundle_application_course_courses_{{ course.id }}">
                        <input type="checkbox"
                               id="my_mainbundle_application_course_courses_{{ course.id }}"
                               name="my_mainbundle_application_course[courses][]"
                               value="{{ course.id }}"
                               {% if course.id in form.courses.vars.value and form.courses.vars.value[course.id] %}checked="checked"{% endif %}>
                        <span class="name">{{ course.name }}</span>
                        <span class="subject">({{ course.subject }})</span>
                        -
                        <span class="credits">{{ course.credits }} hours</span>
                    </label>
                </div>
            </div>
        </div>
        {% endfor %}
    </section>
    {% endfor %}

    {% do form.courses.setRendered %}
    {{ form_row(form.save) }}

{{ form_end(form) }}

【讨论】:

  • 对设置渲染属性的选项很有帮助!
猜你喜欢
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多