Passing Data to Buildform() in Symfony 2.8, 3.0 and Above

Passing data to buildForm() in Symfony 2.8, 3.0 and above

This broke some of our forms as well. I fixed it by passing the custom data through the options resolver.

In your form type:

public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->traitChoices = $options['trait_choices'];

$builder
...
->add('figure_type', ChoiceType::class, [
'choices' => $this->traitChoices,
])
...
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'trait_choices' => null,
]);
}

Then when you create the form in your controller, pass it in as an option instead of in the constructor:

$form = $this->createForm(ProfileEditType::class, $profile, [
'trait_choices' => $traitChoices,
]);

How to pass parameter to FormType constructor from controller

Thanks for your time! i resolved this myself:

I removed parameter from NewsType constructor and added data to postedBy form field using $options array, and passed data to $options array from controller, please check following:

NewsType

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('postedBy', HiddenType::class, array(
'data' => $options['postedBy']
)
)
;
}

// WARNING: this is a MANDATORY block! Only options described here will be allowed to be passed.
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'postedBy' => null,
));
}

Controller

$form = $this->createForm(NewsType::class, $news, array(
'postedBy' => $this->getUser()->getFullname(),
);

UPDATE:
Please use below code if you want to access $options array from addEventListener:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$postedBy = $event->getForm()->getConfig()->getOptions()['postedBy'];
}

Hope it helps somebody! 

Symfony 2.8/3.0 upgrade: how to deal with form types with variable parameters?

Well, after digging this topic a bit more, someone already asked the question directly in the PR concerning this change in Symfony 2.8.

And the answer is that the pattern I was doing is not possible anymore, so I see 2 solutions to my problem:

  • Create as many classes as I had services for my custom types instead of using all the time the same class, and make these classes extend an abstract one (in my example: create Gender1Type and Gender2Type classes that extend a AbstractGenderType abstract class)
  • Keep only one class, but add options to it to pass my specific parameters.

Symfony2 passing values to collection form type

Use the constructor in AddressType, its works for me..

CustomerType:

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
...
->add('addresss', 'collection', array(
'label' => 'customer.address',
'type' => new AddressType($your_variable),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
))
;
}

AddressType:

private $your_variable;

public function __construct($variable)
{
$this->your_variable= $variable;
}
...
public function buildForm(FormBuilderInterface $builder, array $options){
$your_variable = $this->your_variable;
'query_builder' => function(CityRepository $cr) use ($your_variable) {
return $cr->getCityQB($your_variable);
},
}

Define form as service in symfony 3.0

Sorry, I misread your question at first. Now, the correct answer:

If your form type needs to have a dynamic configuration setting (e.g. a parameter), a form type option should be created instead. This allows to dynamically change this setting:

class MyFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $form, array $options)
{
$options['your_setting']; // read the option
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired('your_setting'); // add a required option
}
}

Usage:

$this->createForm(MyFormType::class, null, [
'your_setting' => 'some value',
]);

Alternatively, you can also default the setting to some static value or to a parameter:

class MyFormType extends AbstractType
{
private $yourSetting;

public function __construct($yourSetting)
{
$this->yourSetting = $yourSetting;
}

// ...

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('your_setting', $this->yourSetting);
}
}

You can read more about this in the OptionsResolver component documentation.

passing data from controller to Type symfony2

You can pass parameters to the form class as follows:

//PlumeOptionsType.php
protected $profile;

public function __construct (Profile $profile)
{
$this->profile = $profile;
}

Then use it in the query_builder of your buildForm:

$profile = $this->profile;

$builder->add('framePlume', 'entity', array(
'class' => 'DessinPlumeBundle:PhysicalPlume',
'query_builder' => function(EntityRepository $er) use ($profile) {
return $er->createQueryBuilder('pp')
->where("pp.profile = :profile")
->orderBy('pp.index', 'ASC')
->setParameter('profile', $profile)
;
},

));

And finally in your controller:

// fetch $profile from DB
$form = $this->createForm(new PlumeOptionsType($profile), $plumeOptions);

Backward compatibility breaks in forms upgrading from symfony2.8 to 3.0

Someone else noticed this and wrote up an issue for it here (https://github.com/symfony/symfony/issues/18662) though he has a typo or two in his sample code. There is also an SO article here (Passing data to buildForm() in Symfony 2.8, 3.0 and above) that was very helpful in figuring this out.

So in my case, in pre-symfony3.0 I used to call the form like this:

$form = $this->createForm(new extraOpeningType($user), $extraOpening);

$user is a variable that I pass in for permission handling purposes in the form data, and $extraOpening is the actual entity matched up with the form. Here is how you now have to pass those variables from now on:

use ExtraOpeningBundle\Form\ExtraOpeningType as extraOpeningType; //this goes in the controller head, among your USE statements
...
$form = $this->createForm(extraOpeningType::class, $extraOpening, ['user' => $user]);

If you prefer not to use the USE statement in the head, you can put the fully qualified path to your Type instead, like this (note the leading backslash on the Type path):

$form = $this->createForm(\ExtraOpeningBundle\Form\ExtraOpeningType::class, $extraOpening, ['user' => $user]);

And on the receiving side, in your form (Type, as symfony terms it), where you previously had a constructor to pull in the passed variable...

class ExtraOpeningType extends AbstractType
{
function __construct($user)
{
$this->user = $user;
}

/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $this->user;

Now it just looks like this:

class ExtraOpeningType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->user = $options['user'];

Though you need to add this custom option that you just created to the list of approved options, otherwise you will be faced with an error saying 'user' is not a valid option. So amend your configureOptions method as below (create that method if you aren't already using it):

class ExtraOpeningType extends AbstractType
{

...

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'user' => null
));
}

Symfony is often a dream, but when it comes to updates it can be a nightmare. Lots of backwards compatibility breaks.

get user from form builder symfony 2.8

You can add TokenStorage to your form Type constructor

private $tokenStorage;

public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}

and make your form Type as service e.g.

app.form.something:
class: Gestion\StageBundle\Form\StageType
arguments: ['@security.token_storage']
tags:
- { name: form.type }

and then you can get user in form Type

$user = $this->tokenStorage->getToken()->getUser();

Making a form type with two separate values in it that you can add several times with symfony 4

You'd need a couple of form types for this and you may need to jiggle your entities a bit. Here's the gist of it:

First you need one for each individual item purchased and its count. The EntityType will give you a select with all your articles, exactly what you are looking for.

// BuyingType.php
$builder->add('article', EntityType::class, ['class' => Article::class]);
$builder->add('count', NumberType::class, [
'constraints' => [
new Count(['min' => 1]),
],
]);

The second one will be a CollectionType representing the whole basket.

// BasketType.php
$builder->add('basket', CollectionType::class, [
'entry_type' => BuyingType::class,
'allow_add' => true,
'allow_delete' => true,
]);

Symfony 2.8 Form Builder isn't working

You just need to get the form out of the builder:

$form = $this->createFormBuilder()
->add('name', 'text', array('required' => true))
->add('phone', 'text', array('required' => true))
->getForm();

In fact createView is a method of Symfony\Component\Form\Form while in your example $form is an instance of Symfony\Component\Form\FormBuilder.



Related Topics



Leave a reply



Submit