I'm trying to fill my ChoiceType with an array, but it looks like it's filled with the IDs and not with the values. The form is correctly displayed, but the choices are '0', '1'... instead of the names in the array.
This is my controller:
$categories = $this->getDoctrine()->getRepository('myBundle:Category')->findAll();
$techChoices = array();
$i = 0;
foreach($categories as $t) {
$techChoices[$i] = $t->getName();
$i = $i + 1;
}
$formOptions = array('categories' => $techChoices);
$document = new Document($categories);
$form = $this->createForm(DocumentType::class, $document, $formOptions);
And this is my buildForm:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', FileType::class)
->add('file_name', TextType::class)
->add('file_description', TextType::class)
->add('file_group', ChoiceType::class, array(
'choices' => $options['categories'],
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'categories' => array(),
));
}
Depending on your Symfony's version (since 2.8), you are building the choice array the wrong way.
From 3.3 documentation :
... where the array key is the item's label and the array value is the item's value.
The correct way to show the categories in your case is using EntityType, this will free up your code mess. You don't have to get/pass categories to form anymore.
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('file', FileType::class)
->add('file_name', TextType::class)
->add('file_description', TextType::class)
->add('file_group', \Symfony\Bridge\Doctrine\Form\Type\EntityType::class, array(
// query choices from this entity
'class' => 'AppBundle:Category',
'choice_label' => 'name',
))
;
}
If you want to use an array directly in form choice type then see https://symfony.com/doc/current/reference/forms/types/choice.html#example-usage, or if you want to use data from a table(entity) then see https://symfony.com/doc/current/reference/forms/types/entity.html#basic-usage
Answer to your question is the array format should be like
['data_to_be_seen1' => value1(id), 'data_to_be_seen2' => value2(id),...]
(see the first link),
all the best
you can directly do this :
$builder
->add('file', FileType::class)
->add('file_name', TextType::class)
->add('file_description', TextType::class)
->add('file_group', ChoiceType::class, array(
'choices' => 'here you pass your categories entities directly',
'choice_label' => 'name',
));
like that, it will do the mapping alone
Related
I can not get value from EntityType. I have last version 3.3.6.
class BuildType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array
$options)
{
$builder
->add('title', TextType::class)
->add('save', SubmitType::class, array('label' => 'Create Post'))
->add('team', CollectionType::class, array(
// each entry in the array will be an "email" field
'entry_type' => TeamType::class,
// these options are passed to each "email" type
'entry_options' => array(
'attr' => array('class' => 'form-control'),
),
'label' => false,
'allow_add' => true,
'prototype' => true,
'mapped' => false
));
}
}
class TeamType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array
$options)
{
$builder
->add('name', EntityType::class, array(
'placeholder' => 'Choice a champ',
'required' => true,
'class' => 'AppBundle:Champions',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'attr' => array('class' => 'dropdown'),
));
}
I tried all but i cannot take value of 'name' of TeamType. After submission form, i do
foreach ($form["team"]->getData() as $value) {
'name' => $value['name']
but the value is empty. If i try dump request and the value is there. The other values i can get it and save in Database. Only EntityType i can not.
Someone know how do?
EntityType returns as the object. You should use model getter functions.
$form->get('name')->getData()->getId(); // getName() vs..
Here is a similar example.
symfony how get selected data from select
I suppose that you are using ManyToOne relationship.
With AJAX
if you are trying get data after submitted, You can do this first in your view:
$('#elementWhereYouAreTEAMType').find('input').each(function (i,v) {
var valTeam = $(this).val(); //take value
// adding data, create an associative array.
formData.append("team["+ i +"]", valTeam);
});
You must put formData like data argument to ajax JQuery
Now, server side:
public function createTeamNow(Request $request) {// ajax
$teams = $request->request->get('team'); // getting array
if(!is_null($teams)) {// if user added team
foreach ($teams as $team) {
// dump($team);
//create an instance for each element, it does not replace a data with the above
$teamType = new TeamType();
$teamName->setName($team);
$this->em->persist($teamType);
}
}
}
Without AJAX
/**
* #Route("/slim/1" , name="data_x")
*/
public function slimExampleAction(Request $request)
{
$form = $this->createForm(TeamType::class);
$form->handleRequest($request);
if ($form->isSubmitted() /*&& $form->isValid()*/) {
// When you've ManyToOne relationship, that field returns ArrayCollection class, it has several method to get data on differents ways, iterate with it, for example toArray is one
$data = $form->getData();
dump($data->getDescription()->toArray());die;
}
return $this->render('AppBundle:view.html.twig', array(
'form' => $form->createView(),
));
}
Sorry in advance for the quality of my English
I would create a form to create a Employee. Employee and Team are connected with the ManytoOne bidirectional Relation, Team and Division are connected with the ManytoOne bidirectional Relation, and Division and Center are connected with the manytoOne bidirectional Relation. In my form I want to be able to filter the list of Teams with Javascript, according to the choice made on a first select on Center then Division to reduce the list of Teams.
Here is my code :
EmployeeType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('birthDate', DateType::class)
->add('firstName', TextType::class)
->add('name', TextType::class)
->add('isActive', CheckboxType::class, array('required' => false))
->add('employeePicture', EmployeePictureType::class)
->add('team', TeamType::class)
->add('save', SubmitType::class);
}
TeamType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('shortName',EntityType::class, array(
'class' => 'RTELiveWorkingBundle:Team',
'choice_label' => 'shortName',
'placeholder' => 'Choisir une équipe'
))
->add('divsion', DivisionType::class);
}
DivisionType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('shortName',EntityType::class, array(
'class' => 'RTELiveWorkingBundle:Division',
'choice_label' => 'shortName',
'placeholder' => 'Choisir un GMR'
))
->add('center', CenterType::class);
}
And CenterType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('shortName',EntityType::class, array(
'class' => 'RTELiveWorkingBundle:Center',
'choice_label' => 'shortName',
'placeholder' => 'Choisir un centre'
));
}
My controller :
public function addAction(Request $request) {
$employee = new Employee();
$form = $this->createForm(EmployeeType::class, $employee);
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($employee);
$em->flush();
return $this->redirectToRoute('rte_live_working_employee_view', array('id' => $employee->getId()));
}
return $this->render('RTELiveWorkingBundle:Employee:add.html.twig', array('form' => $form->createView()));
}
My forms :
I have the error :
Catchable Fatal Error: Method
RTE\LiveWorkingBundle\Entity\Team::__toString() must return a string
value
But I have to implement __toString() in my entity :
public function __toString()
{
return $this->getShortName();
}
have you got an idea ?
I have the following form that contains data from the database it still WIP ( i'm missing a few fields that i didn't add yet).
The form loads data in the first select and based on that select i use ajax to populate a second select with options based on the first select ( basically the associations to the selected value). And from there again another select with certain options and so on and at the end when i submit the form i want to generate a report from database based on the data.
For the moment i'm stuck with the second field because i always get an error:
This value is not valid.
The form class:
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('survey', EntityType::class, [
'class' => SurveyManager::class,
'placeholder' => 'Choose option',
'attr' => [
'class' => 'field-change',
],
])
->add('headquarter', ChoiceType::class, [
'choices' => [],
])
->add('submit', SubmitType::class, [
'label' => 'Save',
])
;
}
I'm not reall sure how to fix the error or how should i handle this type of form. Can you help me out guys ?
Based on the answer i did this
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
$form->add('headquarter', EntityType::class, [
'class' => HeadQuarterManager::class,
'query_builder' => function(HeadQuarterManagerRepository $er) {
return $er->getHeadquarter($data['survey']);
},
]);
}
);
But i'm getting this error:
Notice: Undefined variable: data
Not really sure how to pass the data to the getHeadquarter method so i can return an array of id => name for the select.
When you run the function $form->isValid(), it checks against the form it built in the buildForm function. Any extra fields/value that aren't there will cause this error.
You can change this behaviour by using form events.
In the end this is how i did it:
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('survey', EntityType::class, [
'class' => SurveyManager::class,
'attr' => [
'class' => 'field-change',
],
])
->add('submit', SubmitType::class, [
])
->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
$modifier = $data['survey'];
$form->add('headquarter', EntityType::class, [
'class' => HeadQuarterManager::class,
'query_builder' => function (HeadQuarterManagerRepository $er) use ($modifier) {
return $er->getHeadquarter($modifier);
},
]);
}
);
}
Whats the best way to set a collection of key/values pairs (obtained from MySQL) as a choice field 'choices' inside a controller?
I think about something similar to :
$form = $this->createForm(new AddNews(), $news);
$newsList = $this->getDoctrine()
->getRepository('BakaMainBundle:News')->getAllNews();
$titlesList = ...($newsList); // some fuction that extract title=>id
// array from news object collection
$form->get('newsList')->setData($titlesList);
where the AddNews() form looks like :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(...)
->add(...)
->add('accept' , 'submit')
->add('newsList', 'choice', array
(
'mapped' => false,
'required' => true
));
}
Perhaps something like below (assuming Symfony >= 2.7). See docs for field options:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(...)
->add(...)
->add('accept' , 'submit')
->add('newsList', 'entity', array
(
'class' => ''BakaMainBundle:News'',
'choice_label' => 'title',
'mapped' => false,
'required' => true
));
}
You could get your "news" directly from your formType file, using your repository, like that:
private function getNews(){
$newsList = $this->getDoctrine()
->getRepository('BakaMainBundle:News')->getAllNews();
$titlesList = ...($newsList); // some fuction that extract title=>id
// array from news object collection
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(...)
->add(...)
->add('accept' , 'submit')
->add('newsList', 'choice', array
(
'mapped' => false,
'required' => true,
'choices' => $this->getNews()
));
}
I'm having dificulties trying to set on my form the selected values on the preferred choices.
I have a class calendar that can have multiple taxes:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('possibledigits')
->add('notes')
->add('autogenerateyear', 'checkbox', array('required' => false))
->add('calendartaxes', null, array(
'required' => false,
'multiple' => true,
'expanded' => true
))
;
}
The relation is many to many:
/**
* #ORM\ManyToMany(targetEntity="CalendarTax", indexBy="name", inversedBy="calendarios")
* #ORM\JoinTable(name="contable_schedule_taxes_relation")
*/
private $calendartaxes;
What I was going to do is to try to get the entity of the form and try to get the selected taxes. But I don't know if that is the correct way to do it.
Is there a more elegant way to do it?
I'm using symfony 2.3.
Regards.
I am assuming you have a relationship set up betwween Calendarios and CalendarTax
so before you create the form ... do
$calendarios = new CalendarIOS();
$calendartax = $this->getDoctrine()->getManager()->getRepository('NamBundle:CalendarTax')->find($calendar_tax_id);
$calendarios->addCalendarTax($calendartax);
now when you send the entity over to the formbuilder...you will have that perticular calendartax checked... :)
Finally I use the preferred_choices of the choice.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$calendario = $builder->getData();
$taxesId = array();
foreach($calendario->getCalendartaxes() as $tax){
$taxesId[] = $tax;
}
$builder
->add('name')
->add('possibledigits')
->add('notes')
->add('autogenerateyear', 'checkbox', array('required' => false))
->add('calendartaxes', null, array(
'required' => false,
'multiple' => true,
'expanded' => true,
'preferred_choices' => $taxesId,
))
;
}
Making one more query and getting the calendar of the form builder.
The comment given by #Hakim was the one that put me on the right path.
Thanks!