Symfony creates empty association when checkbox used on embedded form - symfony

I have a form for Person that has an embedded form for Address (bi-directional one to one relationship, with Address as the owning side w/ FK).
If a user submits the form, Symfony will initialize an empty Address object and assign it to the $address property on the $person object. Instead, I want Symfony to recognize all the form fields for Address were blank and it should NOT initialize an empty Address object.
Is this possible?
EDIT: I discovered that this only happens when I have a checkbox on the embedded form type. If there is no checkbox, Symfony will NOT create an empty association object. I think the problem is an unchecked checkbox is assumed to be a "false" value, so Symfony has no choice but to interpret that as a submitted value. Still looking for a reasonable workaround.

It's possible to do this with form events
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
Search for FORM_SUBMIT
However, I find it a bit convoluted.
Consider instead treating Person and Address as independent objects then setting the relation in your controller after checking Address. Something like:
$person = new Person();
$address = new Address();
$formData = array('person' => $person, 'address' => $address);
$builder = $this->formFactory->create('form',$formData);
$builder->add('person', new PersonFormType());
$builder->add('address', new AddressFormType());
...
if ($form->isValid()
{
if ($address was filled in properly)
{
$person->setAddress($address);
}
---
I find the above approach a bit easier to understand than going through the form event stuff.

Related

Within a Callback validator for a Symfony sub-form collection, how do I get the value of a different field?

Let's say I have a Callback validator attached to a field in a collection sub-form that looks like this:
$callback = new Callback([
'callback' => function($obj, $context) {
// Value of field to validate, no problem
$value = $context->getValue();
// Get the form, but gets my parent form
$form = $context->getRoot();
// Try and get other field value I need to validate current field,
// but gets "child "otherfield" does not exist" error.
$otherValue = $form->get('otherfield')->getData();
// continue validation logic...
}
]);
I need the value of another field from the specific form instance for the collection item, but I can't find a way to access the child form instance. How do I do this? I can access the list of forms for the collection by using the parent field that holds the collection, but I need the specific instance that this is validating.
It's Symfony version 3.3, but I can't find anything in a later version, either.

Non-mapped form, EntityType and data attribute

I use an EntityType to create a form, but not mapped on an entity. The form is long and the user re-use the same options many times, then when he valid the form, if it's valid, I store the $form->getData() in session.
When I generate the form I inject the $data. It works well for all options, except the EntityType, I don't understand why...
In the $data, I've an ArrayCollection with the objects selected in the EntityType, but the form doesn't select it. I've used mapped = false, because if I remove it I've an error:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
Someone I've an idea how to do ?
Settings mapped = false shouldn't be the solution in this case, because you need to write the stored data into this field, right? so mapped = false avoid it (see more about mapped option here)
The problem here is that the EntityType need to get the id value from each item and it requires that these items are managed actually by EntityManager:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
An entity is in MANAGED state when its persistence is managed by an EntityManager. In other words, an entity is managed if its fetched from the database or registered as new through EntityManager#persist.
In you case, these entities comes from session, so you have two option:
Re-query the stored entities from database:
if (isset($data['foo']) && $data['foo'] instanceof Collection) {
$data['foo'] = $this->getDoctrine()->getRepository(Foo::class)->findBy([
'id' => $data['foo']->toArray(),
]);
}
Or, set a custom choice_value option to avoid the default one:
$form->add('foo', EntityType::class, [
'class' => Foo::class,
'choice_value' => 'id', // <--- default IdReader::getIdValue()
]);

Assigning a default value to a oneToMany association

I have a basic Symfony2/Doctrine2 question. I have two entities the first called "Column" that has OneToMany issues, entity "Issue". And the Issue entity has a ManyToOne relationship with the entity Column. When I create a new Issue I wish to assign a default value for the column.
If I create a hidden field in IssueType.php and assigned a default value I cannot save the submitted form because I get an error about assigning a string to setColumn and not an instance of the Column entity as defined in my Issue entity (see below).
public function setColumn(\WebConfection\ServiceDeskBundle\Entity\Column $column)
{
$this->column = $column;
return $this;
}
Can anybody please advise on the best way to accomplish this? I have read a few articles but am a tad confused and not sure which way to jump. An idiot friendly answer would be greatly appreciated.
You don't really need a hidden field for this to work. Just set the right (default) Column on the Issue you want to add within your action,
// ...
$issue = new Issue();
$issue->setColumn($yourDefaultColumn);
$form = $this->createForm('your_issue_form', $issue);
// ...

How to create a unique form using multiple entities fields in symfony2

I want to create a form using some fields from multiple entities. I have all the distinct entites needed already created and i am not using form classes. I need to know how to do to render a form and handle its data so i can save them to the correct tables in my database.
Here is a part of my controller in charge of doing that
public function createPublicSpaceAction() {
//My entities
$Room = new Room();
$GuestList = new GuestList();
$Guest = new Guest();
//I need to know what to do from here
return $this -> render('AcmeUserBundle:Default:Forms/createPublicSpace.html.twig', array());
}
I kept trying to find a solution and i came up with the idea that one form needs one entity. So maybe the solution would be to merge those entities in one so i can build the form easily. I would then have to persist data to corresponding tables. But i can't think of how to merge entities.
I figured out a temporary solution. For those who want to know, I manually created an entity that looks like a merge of all the entity I need. This new entity has no link with Doctrine therefore it cannot create a table. Its goal is simply to allow me to build up a form and be able to manipulate data through that form. I then assign all data submitted to corresponding entities fields and persist them to the database.
Once again i know this is not the best solution. But for some reasons I won't tell, it is for me at this moment. I hope this can help some that are in the same situation than me and do not hesitate to post links that could help or better ways to do that.
It is highly recommended to use form classes http://symfony.com/doc/current/book/forms.html#creating-form-classes
They are designed to save time and make a lot of things just easier.
However to answer your question consider the following. Your action needs to handel a post request. So catch the request object with the post data:
use Symfony\Component\HttpFoundation\Request;
public function createPublicSpaceAction(Request $request)
Then get a form builder intance and create the form:
$builder = $this->createFormBuilder();
$builder->add('floor', 'text', array(
'label' => 'Room floor',
'data' => $room->getFloor()
));
add as much form fields as you need. There are several built-in field types: http://symfony.com/doc/current/book/forms.html#built-in-field-types
Create the form:
$form = $builder->getForm();
Pass the form to your template:
return $this -> render('AcmeUserBundle:Default:Forms/
createPublicSpace.html.twig', array(
'roomForm' = $form
));
To get posted data within your action:
if ('POST' == $request->getMethod()) {
$data = $request->request->get("form");
}
And in your template you can render the form by yourself or let twig do the job:
{{ form_widget(form.floor)}}
So this are the most importend things to mention. However you should go through http://symfony.com/doc/current/book/forms.html They actually tell you everything I wrote down.
Good luck ;)

Unset a form field value in symfony2 controller

In a typical Symfony2 form, when a field is invalid, the form is presented again to the user with all fields repopulated and an error on the specific field that has an issue.
In my form, I want to force the user to reenter the values of one field (for security reasons), but keep the rest of the fields populated. Is there any way to unset/clear a fields value from the controller in SF2?
Just set it to null — or whatever an empty value is — on the model object itself.
if ($form->isValid()) {
// ...
} else {
$object->setSomeField(null);
}
After you change the value on the object as shown in the answer below, you need to create the form again and pass the object to the form when you do...
$form = $this->createForm(new YourFormType(), $object);
return $this->render('YourBundle:YourEntityName:yourTemplate.html.twig, (array(
'entity'=>$entity,
'form'=>$form->createView()
));

Resources