Display ManyToOne field in Symfony2 forms? - symfony

I am having two entity files one as user.php and another as usertype.php. now i want to display a login form with 3 fields viz username, password and usertype. the usertype will be a selection that will fetch data from usertype table. here is the code that i wrote inside user.php to create a manytoone field for usertype_id
/**
* #ORM\ManyToOne(targetEntity="Usertype")
*/
protected $usertype;
Below is my Form generation Code
class LoginForm extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('login', 'text', array('label' => 'Username',));
$builder->add('password');
}
}
Now I need to add one more field to my form builder that will be a selection of usertype table.

...
use Acme\YourBundle\Entity\Usertype;
class LoginForm extends AbstractType {
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('usertype', 'entity',
array(
'class' => 'AcmeYourBundle:Usertype'
'label' => 'User Type',
)
);
}
}
You can read more informations about the entity field type wich will give you the options available for this type of field.
Don't forget to add a __toString() method to your model to tell the form builder what to display.
namespace Acme\YourBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Usertype
{
public function __toString()
{
return $this->getName();
}
}

There are other ways to do it, but you can try this:
$builder->add('usertype', 'entity',
array(
'class' => 'YourBundle:UserType
'required' => true, // Choose if it's required or not
'empty_value' => 'User type', // Remove this line if you don't want empty values
'label' => 'Type', // You can put a label here or remove this line
)
);
I hope it helped!

http://symfony.com/doc/2.0/reference/forms/types/entity.html
property¶
type: string
This is the property that should be used for displaying the entities as text in the HTML element. If left blank, the entity object will be cast into a string and so must have a __toString() method.

Related

Symfony2 Nested CollectionType form w/ Dependency injection data not saving

I have a problem with the dependency injection, and saving it to the database, I have a following formType inside another form which i use in two different controller routes which handle the same entity: Creating a new entity and editing it. When i'm trying to create a new entity and set $user field for it, it will save user field as empty string.
class SomeClass extends AbstractType
{
private $tokenStorage;
private $user;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$user = $this->tokenStorage->getToken()->getUser();
$builder
->add('price', null, array(
'label' => 'price',
'required' => true,
'translation_domain' => 'some_translation',
'attr' => array(
'placeholder' => 'price'
)
))
->add('user', HiddenType::class, array(
'data' => $user
));
// dump($user);
// exit(0);
}
I have tried it out and dumped it and debugged and what i've found out is that when i dump $user i get the proper data i need firstName, lastName etc. , but when i submit the data it does not save it to the database instead i get empty string. Then i dumped out the whole form after submit in the controller and found out that the user field is null.
However it does work when i go to edit route and edit the existing entity, but if i create new entity on the edit form it does work on the one that exists, but not the newly made entity.
I have also checked the controller and the Entity class itself and those are not the problem.

symfony filter collection field type like entity field type

I have a form with a collection field type.
I'd like to filter it as we can do for entity field types but I'm not finding the solution.
i found other similar questions but no satisfiable answer so far. Can we do something like :
$builder
->add('userIngredients', 'collection', array(
'type' => new UserImportedIngredientType($this->userIngredients),
'query_builder'=>$this->queryBuilder,
))
;
If not, can we use form listener event to exclude some elements based on the object property ? How ?
This collection represents userIngredients that I want the user to be able to change if they have their property isImported set to true, hence the search for the query_builder solution.
Well, I figured I could do something as simple as build a regular form not attached to a parent entity.
In case this might help someone :
class UserImportedIngredientType extends AbstractType
{
protected $userIngredients;
protected $userImportedIngredients;
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($this->userImportedIngredients as $userImportedIngredient)
{
/**
* #var $userImportedIngredient UserIngredient
*/
$builder
->add($userImportedIngredient->getId(), 'genemu_jqueryselect2_entity', array(
'query_builder'=>$this->userIngredients,
'class' => 'AppBundle:FoodAnalytics\UserIngredient',
'multiple' => false,
'label' => $userImportedIngredient->getName(),
'required'=>false,
'mapped' => false,
'data' => $userImportedIngredient
))
;
}
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_foodanalytics_user_imported_ingredient';
}
public function __construct($userIngredients, $userImportedIngredients)
{
$this->userIngredients=$userIngredients;
$this->userImportedIngredients=$userImportedIngredients;
}
}
I solved it like this in my case with additionally Sonata on top of Symfony. What I did was feeding the 'data' parameter the specifically doctrine queried array of entities result. (In Repository: return $queryBuilder->getQuery()->getResult();)
/** #var MyEntityRepository $myEntityRepository */
$myEntityRepository = $this->getEntityManager()->getRepository(MyEntity::class);
/** #var MyEntity[] $myEntities */
$myEntities = $myEntityRepository->findBySomeCriteriaFilter(
$parameter, Constants::specificConstant
);
$formMapper->add(
// html name=
'myEntityProperty',
\Symfony\Component\Form\Extension\Core\Type\CollectionType::class,
[
// specific form for MyEntity
'entry_type' => new Form\MyEntity\MyEntityType(),
'allow_add' => true,
'label' => false,
'entry_options' => [
'label' => false
],
// the filtered array of entities from doctrine repository query above
'data' => $myEntities,
]
);
Use this instead of sonata_type_model_list, I guess.
Also if you want to filter sonata_type_model, use EntityType instead and use the 'query_builder' option with a Closure and returning the queryBuilder instead of the array of entities. This is all very inconsistent, best don't use symfony and sonata at all.
As far as I know Collection does not have the query_builder option
So you cannot go this way.
Is hard to decipher what you are trying to do with 4 lines of formType.
Your code looks alright, except the unsuppported query_builder, and you are already passing the userIngredients to the constructor.
My though is that if you need to filter this, then you shouldn't do it in the collection Type, but in other place.
EDITED:
On a second though, you are trying to filter the collection in the wrong place. Is not on the base collection , but in :
class UserImportedIngredientType extends AbstractType {
function __construct( $userIngredients ) {
// Do your stuff
}
function buildForm( FormBuilderInterface $builder, array $options) {
// Add here your entity with the query_filter option :)
}
}
Check the other entries in SO over Collections, there are many of them

How to add confirmation checkbox for FOSUserbundle Registration

I am using the FOSUserBundle, how do i add a checkbox that has to be selected for the user to create an account.
Does FOS already cater for this, and perhaps i just have to add a line in the config file, or maybe i have to change the controller some how.
I have added a link to a picture to better explain what i need to do
This is really important, as users must accept the terms and conditions before registration.
You can add simply à field with the option « mapped » at false for doesn't add it in your entity.
$builder
->add('cgu', 'checkbox', array(
'label' => 'Je reconnais…',
'required' => true,
'mapped' => false
))
;
In your form you will have to use class:
Symfony\Component\Validator\Constraints\True;
like this :
<?php
namespace Project\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\True;
use FOS\UserBundle\Form\Type\RegistrationFormType;
class MyUserRegistrationType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', new RegistrationFormType())
->add('cgu', 'checkbox', array(
'label' => 'Your label',
'required' => true
))
->add('t_and_c', 'checkbox', array(
'property_path' => false,
'constraints' => new True(array('message' => 'Your Confirmation Message','groups' => 'Registration')),
))
;
}
/**
* #return string
*/
public function getName()
{
return 'project_userbundle_user';
}
}
I see two solutions, the first is the legacy create a legacy from that of FOSUserBundle form. But you can have issues at validating your User entity.
I suggest you create a form MyUserRegistrationType.php for example and add FOSUserBundle form and checkbox like this :
<?php
namespace Project\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType;
class MyUserRegistrationType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', new RegistrationFormType())
->add('cgu', 'checkbox', array(
'label' => 'Your label',
'required' => true
))
;
}
/**
* #return string
*/
public function getName()
{
return 'project_userbundle_user';
}
}
Ajeet's answer is correct for validating the form, but the user can submit the form and then an error will show. There is another option if you want to prevent the user from being able to submit the form at all and you need to use javascript or jQuery. I use this and I actually hide the submit button until the user has filled out all items needed. Below is a simple script using jQuery:
<script>
$('#chkSelect').click(function(){ validatechecked(); });
validatechecked(){
var isChecked = $('#chkSelect').prop('checked');
if(var){
#submit.show();
}
else{
alert("Please agree to the terms to proceed.")
#submit.hide();
}
};
</script>
You will need to adjust the code with the id of your submit button and checkbox. You can add other options to it for more validation.
I use this along with annotations in my entity to give the user quicker feedback and to prevent clearly wrong/incomplete submissions. It is something extra you need to add to your twig file and you probably should put the jQuery code in a separate js file.

Symfony Forms - dynamic number of items

I'm trying to build a product page that will contain a form with a dynamic number of "options" (either select boxes or input fields) depending on the product. After reading the documentation, I can't see how to create a form entity that would work when building this form. I feel like I'm missing something obvious.
What you need to do is basically create form field of collection type, which will be your collection of select boxes, input fields, whatever.
Check documentation and read about embeding forms, it is described pretty well ther
Your parent form:
class ParentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', 'hidden')
->add('name')
->add('yourCollection', 'collection', array(
'type' => new ChildType(),
'label' => 'Label for your child form',
));
}
}
Your child form:
class ChildType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', 'hidden')
->add('category', 'choice')
;
}
}

Symfony 2 not validating entities in a collection form type?

My form uses the uploads collection type. Each element of the collection is of UploadType:
class MultiUploadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('uploads', 'collection', array(
'type' => new UploadType(), // This should be validated
'allow_add' => true,
));
$builder->add('Save', 'submit');
}
}
Using javascript I'm able to add new uploads, but validation doesn't work. I've read many questions here (here, here or here) but I can't find a solution yet.
This is how the upload type looks like, while validation is defined using YAML, as the form has a corresponding entity of type Upload (file can't be blank):
class UploadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', 'file');
$builder->add('description', 'textarea');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'required' => false,
'data_class' => 'App\Entity\Upload'
));
}
}
Validation code:
App\Entity\Upload:
properties:
file:
- NotBlank:
message: Occorre selezionare un file.
- File: ~
From comments disscusion:
Yes, basically each form should have a data class. It has not to be a entity, a simple model class is enough. So you can apply validation to it. To validate embed forms the Valid assert is required and for collections the same but with the option traverse: true.

Resources