Symfony form Set Value of non mapped field from database - forms

I have a TextType label field in my form, my Entity is EAV,
the structure is :
id,
targetId,
entityTargetName,
In my form I have a non mapped field label a dynamic from database, when rendering my form I must send a query to database with targetId and entityTargetName and get the value of label field and set it to the form.
I know that I can do query builder but my field is not a select, it's a TexType
->add('productName ', TextType::class,
array(
'mapped'=>false,
)
)
Any idea ?

You can inject entity repository not just for EntityType field.
You can do the following:
1. Create form in your controller in this way (or something similar):
/** #var FormInterface $form */
$form = $this->get('form.factory')->create(MyFormType::class, null, [
'action' => $this->get('router')->generate('my_action_routename'),
'method' => 'POST',
'entityManager' => $this->getDoctrine()->getManager(),
]);
2. Add configureOptions method to your MyFormType class:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => MyModelClass::class,
'entityManager' => null, // This is important
]);
}
3. Use entity manager in this way in your buildForm method and pass it to default value:
$options['entityManager']->getRepository(ProductRepository::class)->getProductName(targetId, entityTargetName);
Hope this helped!

Related

Can i pass an own array trough the options from controller to formType

I want to pass an array through this function:
$form = $this->createForm(ProductTypeType::class, $productType, $options);
In symfony4 it seams not possible to pass own parameter through the $otions to the formType.
It is possible as you describe. Here is an example:
$form = $this->createForm(
EntityType::class,
$entity,
['optionOne' => true] //this is the array of options (in this case just one)
);
In EntityType you could then use this option like this (for example, add a field):
if($options["optionOne"]){
$builder
->add('addedField')
//....or do something else...
Also in EntityType don't forget to set the default value for your option:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Entity::class,
'optionOne' => false,
]);
}

Symfony4 Forms - How do you conditionally disable a form field?

So what is the best way to have a form render effectively the same form over and over again, with conditionally disabled fields based on the Entity's property values?
I have an Invoice Entity and need a form for creating the invoice, and also the same form with various fields disabled at various stages of the invoicing process (generated, sent, paid etc).
I think the simplest answer is to disable them dynamically in the twig template via form_row options but surely this will affect server side validation of the form as it is not aware the field has been disabled?
What is the best way to disbale a field based on a value in the database?
EDIT 1:
Changed question from Dynamically disable a field in the twig template or seperate class for each form? to Symfony4 Forms - How do you conditionally disable a form field?
Thanks to #Cerad. The answer is in fact Form Events
In the form type (App\Form\InvoicesType for me), add a method call to the end of the builder:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$plus_thirty_days = new \DateTime('+28 days');
$builder
->add('client', EntityType::class, array(
'class' => Clients::class,
'choice_label' => 'name',
'disabled' => false,
) )
// the event that will handle the conditional field
->addEventListener(
FormEvents::PRE_SET_DATA,
array($this, 'onPreSetData')
);;
}
and then in the same class, create a public method named the same as the string in the array (onPreSetData for this example):
public function onPreSetData(FormEvent $event)
{
// get the form
$form = $event->getForm();
// get the data if 'reviewing' the information
/**
* #var Invoices
*/
$data = $event->getData();
// disable field if it has been populated with a client already
if ( $data->getClient() instanceof Clients )
$form->add('client', EntityType::class, array(
'class' => Clients::class,
'choice_label' => 'name',
'disabled' => true,
) );
}
From here you can update the field to be any valid FormType and specify any valid options as you would a normal form element in the From Builder and it will replace the previous one, laving it in the same original position in the form.

How to pass default data when creating a form holding a CollectionType?

I am trying to create multi import data, so I need many form collection this same class in one place. I can do this using collection type.
I created pictures Class with have one field: pictures and it is arrayCollection type like this:
class Pictures {
protected $pictures;
public function __construct()
{
$this->pictures = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addPicture(Picture $picture)
{
$this->pictures[] = $picture;
return $this;
}
public function removePicture(Picture $picture)
{
$this->pictures->removeElement($picture);
}
public function getPictures()
{
return $this->pictures;
}
}
Next I created pictures form with collection to pictureType.
$builder
->add('pictures', 'collection', array(
'prototype' => false,
'by_reference' => true,
'entry_type' => PictureType::class,
'options' => array('label' => false))
)
;
Next I have picture Entity with fields for example name, width, height, image (nevermind).
So my PictureType is a simple form fith fields that same like Entity (standard).
Now I try to render this form and add some picture in controller (not from database). Then I create Picture Object and next I add it to pictures->addPicture($picture);
$pictures = new Pictures();
foreach($data as $d){
$picture = new Picture();
$picture->setName($d['title']);
$picture->setImage($d['thumbnail_400_url']);
$picture->setWidth($d['width']);
$picture->setHeight($d['height']);
$pictures->addPicture($picture);
}
$form = $this->createForm('PicturesType', $pictures, array(
'action' => $this->generateUrl('dashboard_fotolia_save'),
'method' => 'POST',
));
After it if rendered form is ok. I can see and change values.
But after submit form data disapear. I hope data will be stored in response but not:(
I want to use it only for create new object. Could you help me?
Form errors: This form should not contain extra fields
Actually it seems that your PicturesType holds a pictures field since you add it with :
$builder->add('pictures', 'collection', ...
So you got a form type with holds an array of data with a key 'pictures' for the corresponding fields.
You may want to set it by :
$form = $this->createForm('PicturesType', array('pictures' => $pictures), ...

field array type in entity for form choice type field symfony

I would like to create a UserForm for create user in my system backend.
I use a entity with a 'role' field as type array
I want use a select choice field type Form with that entity field.
I use a transformer class system for convert data between Entity and form.
but I turn around in my head and nothing run correctly.
When I use options 'multiple' of choice type, my field display correctly but I don't want to display and select multiple value for this field.
I have Notice: Undefined offset: 0 error
or
I have ContextErrorException: Notice: Array to string conversion
Here few essential code :
UserForm class
$builder->add($builder->create('roles', 'choice', array(
'label' => 'I am:',
'mapped' => true,
'expanded' => false,
'multiple' => false,
'choices' => array(
'ROLE_NORMAL' => 'Standard',
'ROLE_VIP' => 'VIP',
)
))->addModelTransformer($transformer));
transformer Class
class StringToArrayTransformer implements DataTransformerInterface
{
public function transform($array)
{
return $array[0];
}
public function reverseTransform($string)
{
return array($string);
}
}
controller method
$user = new User(); //init entity
$form = $this->createForm(new UserForm(), $user);
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($form);
$em->flush();
return $this->redirect($this->generateUrl('task_success'));
}
entity part
/**
* #ORM\Column(name="roles", type="array")
*/
protected $roles;
public function getRoles()
{
return $this->roles;
}
public function setRoles(array $roles)
{
$this->roles = $roles;
return $this;
}
My field roles entity must be a array for run correctly the security component Symfony
can you help me to understand why this field form refuse to display ?
I already readed others questions in same issue but there is anything that I don't understand because nothing help me to resolve my problem.
If you can help me with MY particular context...
Thank for support
because security symfony component integration
If you only need the "getRoles" method because of the interface you are implementing, it is simpler (and cleaner) to do the following:
Change the entities field again to role with type string
Rename your getter and setter to getRole() and setRole()
and add a getRoles method like this:
public function getRoles()
{
return array($this->role);
}
In your form type, change the field name to "role" and 'multiple' => false
Remove your model transformer
This should be the solution ;)

How to set as a default value in a Symfony 2 form field the authentified username from the FOSUserBundle

i find this snippet useful indeed to put a default value in my form while creating it
$builder
->add('myfield', 'text', array(
'label' => 'Field',
'data' => 'Default value'))
;
what if i want to replace 'default value' with an authentified person from the FOSUser bundle? ( that return true to is_granted("IS_AUTHENTICATED_REMEMBERED"))
i can retrieve that name on a twig file with
{{ app.user.username }}
i have also done it in a controller method with
$username=$this->container->get('security.context')->getToken()->getUser()->getUsername()
but i can't manage to make this working in my form!
i am not sure i understand that container thing well ...neither how to transfer variables betweenn classes and controller...
something around this maybe??
->add('myfield', 'text', array(
'label' => 'Field',
'data' => FOS\UserBundle\Model::$this->getUsername()))
You can passe variable from your controller to your form :
in your controller :
$username=$this->container->get('security.context')->getToken()->getUser()->getUsername()
$form = $this->createForm(new MyFormType($username), $entity);
in your form :
protected $username;
public function __construct (array $username = null)
{
$this->username = $username ;
}
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('myfield', 'text', array(
'label' => 'Field',
'data' => $this->username))
}
Another way to set default values into a form is to set them on the underlying data object for the form, as in this example from the Symfony documentation on building a form:
public function newAction()
{
// create a task and give it some dummy data for this example
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task', 'text')
->add('dueDate', 'date')
->getForm();
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
In this example, the form's underlying data object is a Task and the values set on the task are the default values to be displayed in the form. The task object is not persistent. This approach works just as well with a form class and assuming the underlying object for your form is a User would look something like this:
$username = $this->container->get('security.context')->getToken()->getUser()->getUsername();
$user = new User();
$user->setUsername($username);
// could set any other default values on user here
$form = $this->createForm(new MyFormClass(), $user);
The disadvantage of this approach is if the form is used in many places requiring the same defaults the code would be repeated. This is not a situation I've come across so far - my User forms are re-used for create/edit but edit doesn't require the defaults.