I need to use an Event Listener since I need different things to be displayed in my form whether it is new or an already existing entity. I can manage that.
I have wrote a Form Extension to support this use case without changing type of fields.
1) Create extension class.
namespace AppBundle\Form\Extension\ModelTransformerExtension
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ModelTransformerExtension extends AbstractTypeExtension {
public function getExtendedType() {
return FormType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
if (isset($options['model_transformer'])) {
$builder->addModelTransformer($options['model_transformer']);
}
}
public function configureOptions(OptionsResolver $resolver) {
parent::configureOptions($resolver);
$resolver->setDefaults(array('model_transformer' => null));
}
}
2) Register this extension as an application service.
services:
app.form.extension.model_transformer:
class: AppBundle\Form\Extension\ModelTransformerExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
3) Define model_transformer
option to any DataTransformer implement when building the form.
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->addEventListener(FormEvents::PRE_SET_DATA, function ($event) {
$builder = $event->getForm();
$builder->add('myField', TextType::class, array(
'model_transformer' => new MyModelTransformer()
));
});
}
This idea can be extended to support addViewTransformer
method as well.
Short answer: You can´t add the transformer inside the listener because the form is already locked.
Long answer: There are some solutions. The most common, at least for me, is to a create a Custom form type where you add your transformer. Then you add your custom form how you would normally do in the event listener:
class ElementCustomType extends AbstractType {
private $em;
public function __construct(EntityManager $entityManager)
{
$this->em = $entityManager;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->addModelTransformer(new ElementObjToStringTransformer($this->em))
;
}
public function getParent() {
return 'text';
}
public function getName() {
return 'elementCustom';
}
}
Define your form as a service:
app.form.type.custom_element:
class: AppBundle\Form\Type\ElementCustomType
arguments: [@doctrine.orm.entity_manager]
tags:
- { name: form.type, alias: elementCustom }
Use the form in the listener as your would normally do:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$element = $event->getData();
$form = $event->getForm();
$form->add('element', 'elementCustom')
});