Symfony动态添加或删除子表单

时间:2017-07-07 07:02:30

标签: javascript symfony

我的构建器

有一个表单类MyClassType
$builder->add('options', ChoiceType::class, [
'choices' => [
    'option1',
    'option2',
    'option3',
    'option4'
]])
// some other stuff
->add('subform1', Subform1Type::class)
->add('subform2', Subform2Type::class)
->add('subform3', Subform3Type::class);

的视图
{{ form_start(form) }}
    {{ form_label(form.options) }}
    {{ form_errors(form.options) }}
    {{ form_widget(form.options) }}

    {{ form_label(form.subform1) }}
    {{ form_errors(form.subform1) }}
    {{ form_widget(form.subform1) }}

    {{ form_label(form.subform2) }}
    {{ form_errors(form.subform2) }}
    {{ form_widget(form.subform2) }}

    {{ form_label(form.subform3) }}
    {{ form_errors(form.subform3) }}
    {{ form_widget(form.subform3) }}
{{ form_end(form) }}

和我的控制器类功能

$myClass = new MyClass();
$form = $this->createForm(MyClassType::class, $myClass);
$form->handleRequest($request);

return $this->render('default/myClassView.html.twig',[
    'form' => $form->createView()
]);

我想要做的是根据我选择的选项获得子表单。例如,option1给了我subform1,但是像option4这样的东西给了我subform2和subform3。

我想这样做是因为我将子窗体数据的ManyToOne关系转换为MyClass,但MyClass有时只有subform1等的数据。

我不确定该怎么做。这是EventListeners的用途吗? 我的意思是:在MyClassType

$builder->addEventListener(
    FormEvents::PRE_SET_DATA // or something similiar
    function (FormEvent $event) {
        // do some magic here
    }
);

还是可以做一些JavaScript魔术?我真的不想隐藏我的子表单,因为它仍然存在

1 个答案:

答案 0 :(得分:0)

我想我自己解决了。所以我会给你我做的。 如上所示,将EventListener添加到MyClassType

$builder->addEventListener(
    FormEvents::PRE_SET_DATA 
    function (FormEvent $event) {
        $entity = $event->getData();
        $form = $event->getForm();
        if($entity->getSubform1() !== null){
            $form->add('subform1', Subform1Type::class);
        }
    }
);

作为替代方案,您可以添加EventSubscriber

$builder->addEventSubscriber(new AddFormFieldsSubscriber());

并编写一个新类

class AddUrkundenFieldsSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(FormEvents::PRE_SET_DATA => 'preSetData');
    }

    public function preSetData(FormEvent $event)
    {
            $entity = $event->getData();
            $form = $event->getForm();
            if($entity->getSubform1() !== null){
                $form->add('subform1', Subform1Type::class);
            }
    }
}

在我的Controller类中,我使用$ _SESSION存储我的myClass,如

public function indexAction(Request $request)
{
    $session = $this->get('session');
    if(!$session->get('myClass')){
        $myClass = new MyClass();
    } else {
        $myClass = $session->get('myClass')
    }

    // create and handle form etc

    if($form->isSubmitted()) {
        $myClass = $form->getData();
        if($myClass->getSubform1() === null) {
            $myClass->setSubform1(new Subform1());
            $session->set('myClass', $myClass);
            return $this->redirectToRoute('thisPage');
        } else { /* redirect to another page */ }

    retrun /* create form view */;
    }}

我还必须在Subform1 Class

中实现以下功能
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => 'AppBundle\Entity\Subform1',
    ]);
}

在Twig文件中,您可以执行类似

的操作
{% if form.subform1 is defined %}
{{ form_widget(form.subform1) }}
{% endif %}