Pass array of data to form - symfony

I'm using symfony and I need to pass two arrays so I can make a selectable list.
For now in form builder I have this:
->add('city', EntityType::class, [
'label' => 'Select city',
'class' => Cities::class,
'choice_label' => 'title',
'choice_value' => 'title'
])
It throws me all cities in the list. I want to filtrate them. I've done filtration on my controller like this:
$capitals = $cityRepository->findBy(['cityType' => CityType::capital()->id()]);
$villages = $cityRepository->findBy(['villageType' => CityType::village()->id()]);
this returns me two arrays: capitals and villages.
How can I pass them to the form ?

In your controller :
$form=$this->createForm(YourFormType::class, $yourEntity, array(
'capitals'=>$capitals,
'villages'=>$villages
));
In your form :
public function buildForm(FormBuilderInterface $builder, array $options) {
/** #var array $capitals */
$capitals=$options['capitals'];
/** #var array $villages */
$villages=$options['villages'];
$builder->add('city', EntityType::class, array(...)
->add('vallacap', ChoiceType::class, array(
'mapped'=>false, //Make sure it's not mapped to any entity
'choices'=>array(
'Capitals'=>$capitals,
'Villages'=>$villages
),
'required'=>false,
));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class'=>Personnalisation::class,
'capitals'=>null, // Set default to null in case argument is not passed
'villages'=>null,
));
}

You need to pass the arrays to choices option.
https://symfony.com/doc/current/reference/forms/types/entity.html#using-choices
->add('city', EntityType::class, [
'label' => 'Select city',
'class' => Cities::class,
'choice_label' => 'title',
'choice_value' => 'title',
'choices' => $choices // ------------> This line
])
$choices = array_merge($capitals, $villages);

Related

Field with query should not be blank

How do I add validation constraints "Field is required" in symfony2 PostType class? Any suggestions? I am new in SF2 and I'm just editing what has been done by previous developer.
use Symfony\Component\Validator\Constraints\NotBlank;
class BlogPostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$blogPostCategories = BlogPostCategoryQuery::create()
->filterByBlogPost($builder->getData())
->find();
$categoryIds = array();
foreach ($blogPostCategories as $blogPostCategory) {
$categoryIds[] = $blogPostCategory->getCategory()->getId();
}
$queryOptions = array(
'option_status' => Categorypeer::STATUS_ACTIVE,
'option_category_ids' => $categoryIds
);
$categories = CategoryQuery::create()
->filterActiveCategoriesByOptions($queryOptions)
->find();
$builder->add('category_ids', 'model', array(
'label' => 'Category',
'mapped' => false,
'class' => 'Deal\MainBundle\Model\Category',
'query' => CategoryQuery::create()
->filterActiveCategoriesByOptions()
->orderByName(),
'property' => 'name',
'empty_value' => 'Select categories',
'empty_data' => null,
'required' => true,
'multiple' => true,
'data' => $categories,
'constraints' => array(
new NotBlank(array(
'message' => 'Your message can not be blank! Ouch!'
)),
)
));
Thank you
You should set required => true for this type from the parent form when calling (that's the form type that uses your BlogPostType):
$formBuilder->add('whatever', BlogPostType::class, ['required' => true]);
Also, you could set required = true by default for BlogPostType:
class BlogPostType extends AbstractType
{
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'required' => true
]);
}
}
You can do it with constraints key. Like this:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('message', TextareaType::class, array(
'required' => true,
'constraints' => array(
new NotBlank(array(
'message' => 'Your message can not be blank! Ouch!'
)),
)
))
;
}
do not forget to add uses:
use Symfony\Component\Validator\Constraints\NotBlank;

formBuilder - How to add an entity?

I have two classes : Class and Students. Each class contain one or many student.
In my form (create student), I want a scroll selector with all the available class to put my student in a class.
I have do that :
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('classe', 'entity', array(
'required' => true,
'class' => 'MyCoolBundle:Classe',
'query_builder' => function(ClasseRepository $cr) {
return $cr->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
}))
;
}
But the result is :
Could not load type "entity"
500 Internal Server Error - InvalidArgumentException
After the doc you've to rewrite the field type:
Extract from doc
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
// ...
$builder->add('users', EntityType::class, array(
'class' => 'AppBundle:User',
'choice_label' => 'username',
));
So I think you should try something like :
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
...
...
$builder
->add('name')
->add('classe', EntityType::class, array(
'required' => true,
'class' => 'MyCoolBundle:Classe',
'query_builder' => function(ClasseRepository $cr) {
return $cr->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
}))
;

Symfony2 form queryBuilder find distinct object

I have an Organization entity.
Acme\BaseBundle\Entity\Organization:
type: entity
...
oneToMany:
childOrganizations:
targetEntity: Organization
mappedBy: parentOrganization
manyToOne:
parentOrganization:
targetEntity: Organization
inversedBy: childOrganizations
nullable: true
I have this form:
->add('parentOrganization', 'entity', array(
'class' => "AcmeBaseBundle:Organization",
'property' => 'name',
'required' => false,
'query_builder' => function(EntityRepository $er)
{
return $er
->createQueryBuilder('o')
->select('o')
->add('groupBy', 'o.name');
},
))
Then I would like to show only different organizations. I mean if I have first, second and third organization. Then I have a form for the first organization and I would like to have just two choices in parentOrganization entity field (second and third), but in this case I have three choices (first can be parent of first).
Is there some way to leave out possibility to connect with own org?
EDIT: The problem is that I am working in form class and I don't know how to handle Organization object here. This is my code:
class OrganizationType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, array('max_length' => 100))
->add('type')
->add('parentOrganization', 'entity', array(
'class' => "AcmeBaseBundle:Organization",
'property' => 'name',
'required' => false,
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('o')
->select('o')
->add('groupBy', 'o.name');
}
))
->add('addresses', 'bootstrap_collection', array(
'type' => new AddressType(),
'allow_add' => true,
'allow_delete' => true,
'add_button_text' => '+',
'delete_button_text' => '-',
'by_reference' => false,
'sub_widget_col' => 9,
'button_col' => 3
))
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\Organization'
));
}
public function getName()
{
return 'acme_basebundle_organization';
}
}
If you create form as written in doc (through method createForm of controller), then your current entity available in $options['data']. And your code will look like:
$entity = $options['data'];
...
'query_builder' => function(EntityRepository $er) use ($entity)
{
return $er->createQueryBuilder('o')
->select('o')
->add('groupBy', 'o.name')
->add('where', 'o.id != ?1')
->setParameter(1, $entity->getId());
}

Symfony2 choice field not working

I asked a question here How to use Repository custom functions in a FormType but nobody anwsered, so i did a little digging and advanced a little but i still get this error:
Notice: Object of class Proxies\__CG__\Kpr\CentarZdravljaBundle\Entity\Category
could not be converted to int in /home/kprhr/public_html/CZ_Symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php line 457
Now this is how my CategoryType looks like:
<?php
namespace Kpr\CentarZdravljaBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Bridge\Doctrine\RegistryInterface;
class CategoryType extends AbstractType
{
private $doctrine;
public function __construct(RegistryInterface $doctrine)
{
$this->doctrine = $doctrine;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Kpr\CentarZdravljaBundle\Entity\Category',
'catID' => null,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$someId = $builder->getData()->getId();
$param = ($someId) ? $someId : 0;
$catID = $options['catID'];
$builder->add('name', 'text', array('attr' => array('class' => 'span6')));
$builder->add('file', 'file', array('image_path' => 'webPath', 'required' => false));
$builder->add('parent', 'choice', array(
'choices' => $this->getAllChildren($catID),
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
$builder->add('tags', 'tag_selector', array(
'required' => false,
));
$builder->add('status', 'choice', array(
'choices' => array('1' => 'Aktivna', '0' => 'Neaktivna'),
'required' => true,
));
$builder->add('queue', 'text', array('attr' => array('class' => 'span3')));
}
private function getAllChildren($catID)
{
$choices = array();
$children = $this->doctrine->getRepository('KprCentarZdravljaBundle:Category')->findByParenting($catID);
foreach ($children as $child) {
$choices[$child->getId()] = $child->getName();
}
return $choices;
}
public function getName()
{
return 'category';
}
}
I am accessing the CategoryRepository function findByParenting($parent) from the CategoryType and I am getting the array populated with accurate data back from the function getAllChildren($catID) but the error is there, i think that Symfony framework is expecting an entity field instead of choice field, but dont know how to fix it.
I also changet the formCreate call in the controller giving $this->getDoctrine() as an argument to CategoryType():
$form = $this->createForm(new CategoryType($this->getDoctrine()), $cat, array('catID' => $id));
Ok i managed to resolve the dilemma. The answer was easy all I had to do is change
$builder->add('parent', 'choice', array(
'choices' => $this->getAllChildren($catID),
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
to this:
$builder->add('parent', 'entity', array(
'class' => 'KprCentarZdravljaBundle:Category',
'choices' => $this->getAllChildren($catID),
'property' => 'name',
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
And change the getAllChildren(..) function so that it returns objects
private function getAllChildren($catID)
{
$choices = array();
$children = $this->doctrine->getRepository('KprCentarZdravljaBundle:Category')->findByParenting($catID);
foreach ($children as $child) {
$choices[$child->getId()] = $child->getName();
}
return $choices;
}
I changed it to:
private function getAllChildren($catID)
{
$children = $this->doctrine->getRepository('KprCentarZdravljaBundle:Category')->findByParenting($catID)
return $children;
}
Lots of thanks to user redbirdo for pointing out the choices option on an entity field.
It seems like you are doing something too much complicated.
You are on the right way when you write Symfony framework is expecting an entity field instead of choice field.
To do this, replace:
$builder->add('parent', 'choice', array(
'choices' => $this->getAllChildren($catID),
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
by:
$builder->add('users', 'entity', array(
'class' => 'KprCentarZdravljaBundle:Category',
'property' => 'name',
'query_builder' => function(EntityRepository $er) use($catID) {
return $er->findByParenting($catID);
},
'required' => false,
'empty_value' => '--Izaberite Opciju--'
));
(and you don't need getAllChildren($catID) anymore unless used somewhere else)
http://symfony.com/doc/current/reference/forms/types/entity.html

Symfony empty date field is not required with single_text widget

I created form with date field using single_text widget.
I'm choose this one over choice because I'm using Bootstrap datepicker
Problem I have is that field is always populated with current date instead of being empty.
According to this it should work if i set required to false but id does not.
I tried setting empty_value to empty string same for data but in first case nothing happened probably because this option is for choice fields. In second case I'm getting exception "Expected argument of type "\DateTime", "string" given"
I tried using DataTransformer but didn't make any difference. I found out that for data fields value always goes through DateTimeToLocalizedStringTransformer and if I understand it correctly it is returning empty string if empty value so problem is somewhere further after datatransformers.
One more thing I tried is to set value using attr array and it worked unfortunately the side effect was that populating form with some values doesn't affect date field.
Is there any way to set default value of data field as empty with single_text widget?
Here goes a code
<?php
namespace Psw\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
use Psw\AdminBundle\Form\DataTransformer\EmptyDateTransformer;
use Psw\AdminBundle\Form\DataTransformer\EmptyDateViewTransformer;
class OrdersFilterType extends AbstractType
{
private $admin;
public function __construct($admin=false) {
$this->admin = $admin;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('client', 'entity', array(
'class' => 'PswAdminBundle:User',
'required' => false,
'multiple' => false,
'label' => 'orders.client',
'empty_value' => 'orders.allclients',
'query_builder' => function(EntityRepository $er) {
$qb = $er->createQueryBuilder('u');
return $qb->where($qb->expr()->like('u.roles', '?0'))
->setParameters(array('%ROLE_CLIENT%'));
}
));
if($this->admin) {
$builder->add('staff', 'entity', array(
'class' => 'PswAdminBundle:User',
'required' => false,
'multiple' => false,
'label' => 'orders.staff',
'empty_value' => 'orders.allStaff',
'query_builder' => function(EntityRepository $er) {
$qb = $er->createQueryBuilder('u');
return $qb->where($qb->expr()->like('u.roles', '?0'))
->orWhere($qb->expr()->like('u.roles', '?1'))
->orWhere($qb->expr()->like('u.roles', '?2'))
->setParameters(array('%ROLE_STAFF%','%ROLE_ADMIN%','%ROLE_SUPER_ADMIN%'));
}
));
}
$builder->add('start', 'date', array(
'label' => 'orders.start',
'widget' => 'single_text',
'required' => false,
))
->add('end', 'date', array(
'label' => 'orders.end',
'widget' => 'single_text',
'required' => false,
))
->add('min', null, array(
'label' => 'orders.min',
'required' => false,
))
->add('max', null, array(
'label' => 'orders.max',
'required' => false,
));
}
public function getDefaultOptions(array $options)
{
$options = parent::getDefaultOptions($options);
$options['csrf_protection'] = false;
return $options;
}
public function getName()
{
return 'psw_adminbundle_ordersfiltertype';
}
}

Resources