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);
},
]);
}
);
}
Related
I am making a dynamic form but I can not prefill a field according to the value of the previous field. If the name equals jean i want to add a color field and I want to prefill the jean's favorite color by example...
class TestEventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', ChoiceType::class, [
'choices' => [
'jean' => 'jean',
'pierre' => 'pierre',
'marie' => 'marie',
],
]);
$builder->get('name')->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'addColor']);
}
public function addColor(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
$parentForm = $form->getParent();
if ($data === 'jean') {
$builder = $parentForm->getConfig()
->getFormFactory()
->createNamedBuilder('color', TextType::class, null, [
'auto_initialize' => false,
'required' => false,
// 'empty_data' => wrong behavior
]);
$parentForm->add($builder->getForm());
}
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => TestObject::class,
]);
}
}
If I use empty_data, it puts the value in the field, OK. The problem is that if I want to submit a form with this empty field, it will take the value of empty_data, which is incorrect.
I try data => 'red' but it doesn't prefill the field. I try 'blue' in the third param of the createNamedBuilder method but nothing too.
To add data on a field you can use the value attribute, as example
$builder->add('body', TextType::class, [
'attr' => ['value' => 'red'],
]);
i have a InspectionPlan Form Type which has a product EntityType field, (Products can have attributes i assign some by fixtures) however, the formtype also has a CollectionType Field for another entity called InspectionPlanSections, this uses a InspectionPlanSectionFormType which has a CollectionTypeField for an entity called InspectionPlanQuestions with a InspectionPlanQuestionFormType with allow_add' => true and a prototype, these questions have a relation to the earlier mentioned ProductAttributes, , only the product attributes the earlier submittet Product has should be assignable
class InspectionPlanQuestionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('question', TextareaType::class, [
'attr' => ['class' => 'tinymce'] ])
->add('productAttribute', EntityType::class, [
'class' => ProductAttribute::class,
'placeholder' => 'Attribut auswählen',
'choice_label' => 'name'
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => InspectionPlanQuestion::class,
]);
}
}
this loads all product attributes which is not exactly what i want
class InspectionPlanQuestionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('question', TextareaType::class, [
'attr' => ['class' => 'tinymce'] ]);
$builder->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event)
{
$form = $event->getForm();
$child = $event->getData();
if ($child) {
$form->add('productAttribute', ChoiceType::class, [
'placeholder' => 'forms.product.attribute_placeholder',
'choices' => $child->getInspectionPlanSection()->getInspectionPlan()->getProduct()->getProductAttributes(),
'choice_label' => function ($choice, $key, $value) {
return $choice->getName();
},
]);
}
}
);
}
this gives me the desired attributes in the select, but only after i atleast submitted one section with a question, because if none were submitted, the $event->getData() returns always null
so when i create a fresh InspectionPlan and add a product, submit the form, and then add a Section and questions via javascript, i get no product attributes select field rendered in my question field
Can someone explain me why this works, after i submitted at least one question?
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(),
));
}
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 have created a FormType class called BookType. The method for generating the form is:
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array('required'=>$this->searchForm))
->add('author', 'text', array('required'=>$this->searchForm))
->add('genre', 'text', array('required'=>$this->searchForm));
if(!$this->searchForm) {
$builder
->add('picture', 'text', array('required' => false));
}
$builder
->add('description', 'text', array('required'=>$this->searchForm))
->add('submit', 'submit', array('required'=>$this->searchForm))
;
}
However, whenever I try to access this with the following code:
$book = new Book();
$form = $this->createForm(
new BookType(true),
$book,
[
'action'=> $request->getUri()
]
);
I am seeing the following error message:
The option "required" does not exist. Known options are: "attr", "auto_initialize", "block_name", "disabled", "label", "translation_domain", "validation_groups".
As far as I am aware from the various tutorials I have read, this should be a completely valid parameter. Am I wrong here?
I think error is occurring here:
->add('submit', 'submit', array('required'=>$this->searchForm));
Since 'submit' field does not have 'required' option.