I'm trying to access a list of categories I have in a database and put them into a form in Symfony2.
public function productAddAction()
{
$product = new Product();
$categories = $this->getDoctrine()
->getRepository('AudsurShopBundle:Category')
->findAll();
$form = $this->createFormBuilder($product)
->add('category', 'choice', array(
'choices' => $categories, /* this is wrong */
'multiple' => false,
))
->add('name', 'text')
->add('save', 'submit', array('label' => 'Create Task'))
->getForm();
return $this->render('AudsurAdminBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
How do I go from $categories to an object that I can put into the following part, and it complying with what the function expects?
->add('category', 'choice', array(
'choices' => $categories, /* this is wrong */
'multiple' => false,
))
I know this is basic, but I can't seem to find the right keywords to find the answer (what should I have looked for?)
First off, "this is wrong" is not a specific error message for us to help you very much. It's like saying "my code doesn't work" and not telling us why. Moving on to your actual problem..
You're not using the right Form type to handle the entity type and display it properly. As #Talus mentioned, the Field Type you need is entity. There's a few things you're missing, such as the class parameter and the property parameter (assuming you haven't written a __toString() function in the Entity class.)
$categories = $this->getDoctrine()
->getRepository('AudsurShopBundle:Category')
->findAll();
$form = $this->createFormBuilder($product)
->add('category', 'entity', array(
'class' => 'AudsurShopBundle:Category',
'choices' => $categories,
'multiple' => false,
'property' => 'name', // This needs to be an actual property, I just assumed name
))
->add('name', 'text')
->add('save', 'submit', array('label' => 'Create Task'))
->getForm();
Since you're using all Category entities that exist, the findAll() query is actually not necessary. You can instead go for the basic usage:
$form = $this->createFormBuilder($product)
->add('category', 'entity', array(
'class' => 'AudsurShopBundle:Category',
'multiple' => false,
'property' => 'name', // This needs to be an actual property, I just assumed name
))
->add('name', 'text')
->add('save', 'submit', array('label' => 'Create Task'))
->getForm();
If you're looking for a specific subset of the Categories, you can use the choices property like before or pass a query_builder.
IRC, I think there is a type for that : http://symfony.com/fr/doc/current/reference/forms/types/entity.html
This should help to whatever you want to do, if I understood what you meant. :)
Well you can parse an Array from database:
Create a method in repository findAllArray():
public function findAllArray() {
return $this->getEntityManager()
->createQuery(
'SELECT Category '.
'FROM AudsurShopBundle:Category AS Category'
)
->getArrayResult();
}
Then call it in your controller and get all categories:
$categories = $this->getDoctrine()
->getRepository('AudsurShopBundle:Category')
->findAllArray();
When you have got array, make it suitable for choice (create new array $choices):
$choices = array();
foreach ($categories as $category) {
$choices[$value['id']] = $value['title'];
}
Then put this new array into form:
->add('category', 'entity', array(
'choices' => $choices,
Hope it helped. Have a nice day.
Related
I am calling entity to provide drop down options. I set a place holder value. I tried setting the data value, but regardless placeholder value is alway tag with selected.
My PostFormType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, array( 'attr' => array(
'class' => 'form-control'
)))
->add('price', TextType::class, array( 'attr' => array(
'class' => 'form-control'
)))
->add('artist', EntityType::class, [
'data'=>2,
'placeholder'=>'Choose Artist',
'class'=>Artist::class,
'choice_label'=>'artist',
'query_builder'=> function (EntityRepository $er) {
return $er->createQueryBuilder('artist')
->orderBy('artist.artist', 'ASC');
},
'empty_data' => null,
'attr' => array(
'class' => 'form-control'
)
])
->add('userId', HiddenType::class )
->add('description', TextareaType::class, array( 'attr' => array(
'class' => 'form-control'
)))
->add('purchaseDate','date')
->add('id',HiddenType::class)
;
}
You shouldn't configure data for property artist if it has to be modified by user in the form.
In case you want to set the default value of a new Entity. Even if you do, the change from UI form will not affect as the data attribute will reset the value to 2 as provided after submit.
You can always use Constructor of the relevant Entity to set any default value.
But, as artist is a referenced property. You should do it in Controller before you build the form.
$artist = $em->getRepository("AppBundle:Artist")->find(2);
$entity->setArtist($artist)
// Load the form here. The default value automatically set in the form
Hope this helps!
I've have a formtype that has an entitytype field.
$builder->add('canRead', EntityType::class, [
'attr' => ['style' => 'height:150px;'],
'choice_value' => 'id',
'required' => true,
'multiple' => true,
'expanded' => false,
'class' => 'AppBundle\Entity\User',
'query_builder' => function (EntityRepository $er) {
$qb = $er->createQueryBuilder('e');
$qb->innerJoin('e.roles', 'r')->where('r.role LIKE :role')->setParameter('role', 'ROLE_ADMIN_%')
->orderBy('e.lastName', 'ASC')
->addOrderBy('e.firstGame', 'ASC');
return $qb;
},
]);
In the controller, I call this like that:
$form = $this->createForm(MedicalType::class, null, [ 'data'=>[] ]);
Where the 'data' is meant to be the selected values for the generated multiple select-field.
I've tried to pass a single User object, an array of User id's, arraycollection of Users, etc.. All of my tries before was the part from "query_builder"s results of course.
Did not work neither of them. Does someone know a solution to pass "selected" values for an entitytype field in formbuilder?
Thank you in advance.
The second parameter to createForm() being null seems to be the problem.
Lets say you have an array of user objects:
$data = [$user1, $user2];
Then try creating the form like that:
$form = $this->createForm(MedicalType::class, $data);
or this way:
$form = $this->createForm(MedicalType::class, array(), [ 'data'=> $data ]);
I tried the above solution but it didn't work for me so this might be helpful for someone else.
I had to pass an array of modules to the form so that it will be the default selected values, so in my controller i did this:
function testAction(){
$modules=array();
//here i'm just loading the modules that will be the default selected values
for ($i=7;$i<20;$i++){
$modules[]=$this->getDoctrine()->getRepository("AppBundle:Module")->find($i);
}
//passing the modules to the form
$form=$this->createForm(ModuleFieldType::class, array(), [ 'data'=> $modules ]);
return $this->render("/Security/test.html.twig",array("form"=>$form->createView()));
}
And in my form I did this :
$builder->add('module', EntityType::class, array(
'class' => 'AppBundle\Entity\Module',
'choice_label' => 'libelle',
'label' => 'Modules Enseignés',
'placeholder'=>"selectionez les modules enseigné",
'group_by' => function (Module $module) {
return $module->getDepartement()->getName();
},
"attr"=>array("id"=>"modulesSelect"),
'multiple' => true,
//you need add this to the form in order to read the data
'data'=>$options['data'],
));
The result was like that in the rendered form:
The rendered form
I have an entity Product. My product can have multiple names in different languages. A name in french, a name in english, etc. I don't want to use an automatic translation.
The user will have to write the names in the Product form and select the corresponding language. He can add so many names as he wants thanks to an Add button.
All the languages are created by the admin user (in another form). So, Language is also an Entity which have a name (ex: English) and a code (ex: EN).
I created the Entity ProductName which have a name and a language (that conform to what the user writes in the Product form).
In that case, I don't need to associate Entity ProductName with Entity Language. I just want the language code. So, in my ProductName entity, I have this property :
/**
* #ORM\Column(name="Language_Code", type="string", length=2)
*/
private $language;
My Product form (ProductType) has a CollectionType field in order to add several names.
// Form/ProductType.php
->add('infos', CollectionType::class, array(
'entry_type' => ProductInfosType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'label' => false,
'mapped' => false
))
And ProductInfosType form has 2 fields :
// Form/ProductInfosType.php
->add('name', TextType::class, array(
'attr' => array('size' => 40)
))
->add('language', EntityType::class, array(
'placeholder' => '',
'class' => 'AppBundle:Language',
'choice_label' => 'code',
'attr' => array('class' => 'lang'),
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('l')->orderBy('l.code', 'ASC');
}
))
So, when I go on my form page, I have a block which contains an input text field (Name) and a select field (language). The select field is like this :
<select id="product_infos_0_language" required="required" name="product[infos][0][language]">
<option value=""></option>
<option value="DE">DE</option>
<option value="EN">EN</option>
<option value="ES">ES</option>
<option selected="selected" value="FR">FR</option>
</select>
At this point, everything works well. I created an add button so that the user can add other names, etc...
But, when I submit the form, when I check form data in my ProductController, I noticed that it does not correspond to what I want to store in database.
print_r($form->get('infos')->getData());
// returns :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[language:AppBundle\Entity\ProductName:private] => AppBundle\Entity\Language Object
(
[code:AppBundle\Entity\Language:private] => FR
[name:AppBundle\Entity\Language:private] => Français
)
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
)
)
What I would like is :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[language:AppBundle\Entity\ProductName:private] => FR
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
)
)
I don't want the language object but directly the language code !
That's why I think that I should not use EntityField in ProductNameType form but ChoiceType field.
How can I load all the languages stored in db in the choice field ?
I hope that this explanation is more understandable ;-)
I found the solution thanks to this post : Passing data to buildForm() in Symfony 2.8/3.0
ProductController.php : pass custom data as an option in the createForm() method.
// ...
// build the form
$em = $this->getDoctrine()->getManager();
$product = new Product();
$languages = $em->getRepository('AppBundle:Language')->findAllOrderedByCode();
$form = $this->createForm(ProductType::class, $product, array(
'languages' => $languages
));
ProductType form : pass custom data in the options resolver
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Product',
'languages' => null
));
}
Then, in the buildForm() function, add an entry_options option in the CollectionType field :
$builder->add('infos', CollectionType::class, array(
'entry_type' => ProductInfosType::class,
'entry_options' => array('languages' => $options['languages']),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'label' => false,
'by_reference' => false
));
ProductInfosType form : pass custom data in the options resolver (exactly the same as in the ProductForm)
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\ProductName',
'languages' => null
));
}
Now, you have two alternatives : either you want that your form returns entities or simple strings.
In my example, I just want the language code (like FR, EN, etc.).
Case 1 : return only the language code when the form is posted :
// Form/ProductInfosType.php
// ...
// Convert array of objects in an array of strings
$choices = array();
foreach ($options['languages'] as $lang) {
$code = $lang->getCode();
$choices[$code] = $code;
}
$builder->add('language', ChoiceType::class, array(
'placeholder' => '',
'choices' => $choices
));
// returns :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
[language:AppBundle\Entity\ProductName:private] => FR
)
)
Case 2 : return Language Entity when the form is posted :
// Form/ProductInfosType.php
// ...
$builder->add('language', ChoiceType::class, array(
'placeholder' => '',
'choices' => $options['languages'],
'choice_label' => 'code',
'choice_value' => 'code'
));
// returns :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
[language:AppBundle\Entity\ProductName:private] => AppBundle\Entity\Language Object
(
[code:AppBundle\Entity\Language:private] => FR
[name:AppBundle\Entity\Language:private] => Français
)
)
)
With this solution, we don't need to create our form as a service in order to pass entity manager as an argument. All is managed in the controller and form options.
You should use choice_value of EntityType.
'choice_value' => function ($language) {
return $language->getCode();
},
EDIT: After reading your edit, you're indeed right, do not use EntityType but ChoiceType. To populate choices, I think you should inject LanguageRepository inside your Form using DependencyInjection, and then create a query in your Repository to fetch all Language codes.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$categoryArray = $this->getTreeArray();
$builder->add('category', 'entity', array(
'class' => 'CategoryBundle:Category',
'label' => 'Categories',
'property' => 'name',
'multiple' => true,
'empty_value' => NULL,
'choices' => $customcategoryArray,
));
}
I want to supply customized tree array to entity type form field . The Entity type have multiselect attribute.
The Solution is hidden in Data Transformer , i tryed my best but i can't do this thing . I need help all of you , please help me.
I have a form with a dropdown (select) and I would like to choose the option selected by default:
This is the code that generates the select:
$builder->add('language', 'choice', array(
'label' => 'pages.age.gateway.language.label',
'choices' => array(1 => 'first option', 2 => 'second option'),
));
I've tried the following (suggested here, Symfony2 Setting a default choice field selection):
$builder->add('language', 'choice', array(
'label' => 'pages.age.gateway.language.label',
'choices' => array(1 => 'first option', 2 => 'second option'),
'data' => '2'
));
this didn't work with my code (my understanding of symfony2, I might not be in the right direction).
Another alternative would be using 'preferred_choices' but I'd like to avoid this, as I wouldn't like to modify the order in which the options are displayed.
If your form depends of an entity:
/* Action */
public function myAction()
{
$user = new User();
$user->setLanguage(2); // Set the default option
$form = $this->createForm(new UserType(), $user); // Give the user to the form
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
$user = $form->getData();
// Do something like save / redirect
}
}
return array(
'form' => $form->createView(),
);
}
Also you can set a preferred choice (but not a true default value) thanks to preferred_choices key (it move up the value to the top of the select):
$builder->add('language', 'choice', array(
'label' => 'pages.age.gateway.language.label',
'choices' => array(1 => 'first option', 2 => 'second option'),
'preferred_choices' => 2
));
You want to add option without the value. You can do this with option empty_value.
$builder
->add('gender', 'choice', array(
'label' => 'Gender',
'choices' => array('male', 'female'),
'empty_value' => 'Please select option'
));