1

Symfony version: 3.4

i have a root form is layout form that is including a collection type is named blocks. The content form is belonged to blocks form. I want to use ajax to making user change the value of selector 1 and then the form type 2 is been changed other form type.

The updated selected value can be picked in $request->request in controller.

but I can not get the new data of selector 1 that always is the old data.

LayoutType.php

class LayoutType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class, array(
            'attr' => array(
                'class' => 'form-control'
            ),
            'label' => 'name'
        ));

        $builder->add('blocks', CollectionType::class, array(
            'entry_type' => BlockType::class,
            'entry_options' => array('label' => false),
            'allow_add' => true,
            'allow_delete' => true,
            'required' => false,
            'label' => false
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => '****\Bundle\****Bundle\Entity\Layout'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'layout_form';
    }
}

BlockType.php

class BlockType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class, array(
            'attr' => array(
                'class' => 'form-control layout-block-name'
            ),
            'label' => '名称'
        ));
        $builder->add('contents', CollectionType::class, array(
            'entry_type' => BlockContentType::class,
            'entry_options' => array('label' => false),
            'allow_add' => true,
            'allow_delete' => true,
            'required' => false,
            'label' => false
        ));
    }/**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => '****\Bundle\****Bundle\Entity\LayoutBlock'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'layout_block_form';
    }
}

BlockContentType.php

class BlockContentType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $factory = $builder->getFormFactory();
        $builder->addEventSubscriber(new BlockContentValueFieldSubscriber($factory));
        $builder->add('unit', TextType::class, array(
            'attr' => array(
                'class' => 'form-control block-content-unit',
                'placeholder' => '默认单位'
            ),
            'required' => false,
            'label' => '默认单位'
        ));
        $builder->add('option', EntityType::class, array(
            'class' => '*******Bundle:FormFieldOption',
            'choice_label' => 'name',
            'attr' => array(
                'class' => 'form-control'
            ),
            'label' => '表单选项'
        ));
        $builder->add('type', ChoiceType::class, array(
            'attr' => array(
                'class' => 'form-control select-block-content-form-type'
            ),
            'choices' => array(
                '文本'   => 'textarea',
                '下拉菜单'   => 'select',
                '图片'      => 'image'
            ),
            'preferred_choices' => array('textarea'),
            'label' => 'Form TYpe'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => '****\Bundle\****Bundle\Entity\LayoutBlockContent'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'block_content_form';
    }
}

BlockContentValueFieldSubscriber.php

class BlockContentValueFieldSubscriber implements EventSubscriberInterface
{
    protected $factory;
    public function __construct(FormFactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_SET_DATA => 'preSetData',
        );
    }

    public function preSetData(FormEvent $event)
    {
        $data = $event->getData();
        $form = $event->getForm();
        if (!($data instanceof LayoutBlockContent) || !$data->getBlock()) {
            $form->add('value', TextareaType::class, array(
                'attr' => array(
                    'class' => 'form-control block-content-input-value form-textarea-type'
                )
            ));
        } else {
            $type = $data->getType();
            // $type always is old data not the ajax data
            switch ($type)
            {
                case 'image':
                    $form->add('value', FileType::class, array(
                        'data_class' => null,
                        'attr' => array(
                            'class' => 'form-control block-content-input-value form-image-type'
                        )
                    ));
                    break;
                default:
                    $form->add('value', TextareaType::class, array(
                        'attr' => array(
                            'class' => 'form-control block-content-input-value form-textarea-type'
                        )
                    ));
                    break;
            }
        }
    }
}

enter image description here

enter image description here

Mike Zhang
  • 263
  • 6
  • 10
  • I have move the BlockContentValueFieldSubscriber into BlockContentType and then can change the form type of place two. but the value of new form type is null. when the form type is FileType, the value is not file object. – Mike Zhang Jul 17 '18 at 02:30

0 Answers0