I have a form with a contact list. I want the field "first name" appear with the selected contact value after submit. My problem is that the field appear but I cant set the good data, the field always remains empty.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('contacts', ChoiceType::class, [
'label' => 'Contact',
'placeholder' => 'Choose a contact',
'choices' => $this->getContacts(),
'mapped' => false,
])
->setMethod('POST')
;
$builder->get('contacts')->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
$contactId = $event->getData();
$parentForm = $event->getForm()->getParent();
$contactEntity = $exampleEm->getrepository(Contact::class)->find($contactId);
$firstName = $contactEntity->getFirstName();
// where can I set the 'contactFirstname' data ?
$parentForm
->add('contactFirstname', TextType::class, [
'label' => 'First name',
]);
})
;
}
How to enter the right data so that the field appears pre-filled?
Edit :
I found a method, but it's not terrible:
$parentForm
->add('contactFirstname', TextType::class, [
'label' => 'First name',
'empty_data' => $firstName,
]);
('data' => $firstNamedont work for me.)
$parentForm->get('contactFirstname')->setData($firstName); doesn't work either
Can't you simply set the 'data' option of your TextType field?
// ...
$contactEntity = $exampleEm->getrepository(Contact::class)->find($contactId);
$firstName = $contactEntity->getFirstName();
$parentForm
->add('contactFirstname', TextType::class, [
'label' => 'First name',
'data' => $firstname //here?
]);
EDIT:
According to this post submitted on github, the form field needs to be submitted in order to have it's data changed.
In one of his solutions, he uses the "empty_data" as you did.
In the other one, he adds the field to the builder. Hides it with display: "none"; until the data is submitted.
The docs say
the data of an unmapped field can also be modified directly:
$form->get('agreeTerms')->setData(true);
So try this:
$parentForm
->add('contactFirstname', TextType::class, [
'label' => 'First name',
]);
$parentForm->get('contactFirstname')->setData($firstName);
Maybe using a setter before creating your form ?
https://symfony.com/doc/current/forms.html#building-the-form
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 create 2 forms not linked to any entity in the same controller.
Each form have it owns submitted button.
I never goes to the submitted function of the second form.
I think it is because the 2 forms have same default name 'form'.
The problem is how to change the form name?
Below what I did
public function index(Request $request)
{
$form1 = $this->createFormBuilder()
->add('sn', TextType::class, [
'required' => false,
])
->add('search', SubmitType::class, ['label' => 'Search'])
->getform();
$form1->handleRequest($request);
if ($form1->isSubmitted() && $form1->isValid()) {
//Do something
}
$form2 = $this->createFormBuilder();
$form2->add('Agree', CheckboxType::class, [
'label' => 'Agree',
'required' => false,
]);
$form2->add('detail', SubmitType::class, ['label' => 'Detail']);
$form2 = $form2->getForm();
$form2->handleRequest($request);
if ($form2->isSubmitted() && $form2->isValid()) {
//Do something else
}
return $this->render('search/index.html.twig', [
'form1' => $form1->createView(),
'form2' => $form2->createView(),
]);
}
If you want to modify the form name, use the createNamed() method:
$form1 = $this
->get('form.factory')
->createNamed('my_name', TextType::class, $task);
You can even suppress the name completely by setting it to an empty string.
Running Symfony 4 with Symfony Forms, I have defined a text field in a form builder:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
// .... other fields
$builder->add('referralCode', TextType::class, [
'required' => true,
'label' => 'Referral Code',
'constraints' => [new NotBlank()],
'attr' => [
'placeholder' => 'Enter a six figures Referral Code (e.g. "6EQE7M")'
]
]);
}
According to docs and tutorials, the NotBlank-constraint should be used here. However, it does not work. If I submit the form without any data typed into this text field, no error is shown. Instead a null value will be send into the property of the entity.
What else needs to be done here?
How to get field value in form builder in Symfony.
I have 2 Dropdowns in the form
I want to should the related option in Dropdown2 based on Dropdown1 in when the Page is Opening.
Here is My Form
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use C2Educate\ToolsBundle\Entity\Students;
public function buildForm(FormBuilder $builder, array $options) {
Field 1:
$builder->add('leadSource', 'entity', array(
'label' => 'How did you hear about C2? Source ',
'class' => 'C2EducateToolsBundle:LeadSources',
'query_builder' => function($repo) {
return $repo->createQueryBuilder('p')->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
$leadSource = 1;
$leadSource = 1; - it works when I assign value statically, but I want to get the value of "leadSource" and assign it to $leadSource
I want to get the leadSource and pass it to leadSourceSub query
Field 2:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) {
$form = $event->getForm();
$entity = $event->getData();
$leadSource = $entity->getLeadSourceID();
$form->add('leadSourceSub', 'C2Educate\ToolsBundle\Entity\Students', array(
'label' => ' Source Detail ',
'required' => true,
'class' => 'C2EducateToolsBundle:LeadSourceSubs',
'query_builder' => function($repo) use ($leadSource) {
return $repo->createQueryBuilder('p')
->where('p.lead_source_id =:leadSource')
->setParameter('leadSource', $leadSource)
->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
});
You cannot get form data from $builder, because... it's a form builder, not a form. It doesn't contain any data yet.
To make this work you need to make use of FormEvents. In this case, you probably will need FormEvents::PRE_SET_DATA event listener.
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
// in your case it's C2EducateToolsBundle:LeadSourceSubs
$entity = $event->getData();
$leadSource = $entity->getLeadSource();
// adding this field again will override it.
$form->add('leadSourceSub', 'entity', array(
'label' => ' Source Detail ',
'required' => true,
'class' => 'C2EducateToolsBundle:LeadSourceSubs',
'query_builder' => function($repo) use ($leadSource) {
return $repo->createQueryBuilder('p')
->where('p.lead_source_id =:leadSource')
->setParameter('leadSource', $leadSource)
->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
}
});
Please note that this code is not tested and may need some validation like to check if $entity is what you expect it to be in any case.
My scenario is the following:
If the user choose true from "maxRedemptionForDiscount" and type "0" into the "maxRedemptionForDiscountValue" there should be an error message rendering to the specific field (at the position of the TextType field)
This is the form with an eventListener:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'maxRedemptionForDiscount',
ChoiceType::class,
[
'placeholder' => false,
'multiple' => false,
'choices' => [
true => 'discount.form_fields.set_max_redemptions',
false => 'discount.form_fields.unlimited',
],
'label' => 'discount.form_fields.max_redemption_for_discount',
'translation_domain' => 'entities',
'required' => false,
'error_bubbling' => true,
'attr' => [
'class' => 'maxRedemptionForDiscountSelect',
],
]
)->add(
'maxRedemptionForDiscountValue',
TextType::class,
[
'label' => 'discount.form_fields.set_max_redemptions',
'translation_domain' => 'entities',
'required' => false,
]
)->addEventListener(
FormEvents::PRE_SUBMIT,
[$this, 'onPreSubmit']
);
}
and this is the onPreSubmit function:
/**
* #param FormEvent $event
*/
public function onPreSubmit(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
if ($data['maxRedemptionForDiscount'] == 1) {
if ($data['maxRedemptionForDiscountValue'] == 0) {
$form->addError(new FormError('error message'));
}
}
$event->setData($data);
}
Here is the twig code:
{{ form_row(form.maxRedemptionForDiscount) }}
<div id="maxRedemptionForDiscountValue">
{{ form_row(form.maxRedemptionForDiscountValue) }}
</div>
This render a error message above the form.
But what I want i to render a error message to the specific field.
This does not work:
$form->get('maxRedemptionForDiscountValue')->addError(new FormError('error message'));
If I try this the error message will disappear at the top of my form, but not showing up at the specific field position.
What I am doing wrong here?
First, you should set error_bubbling to false (or remove it as it's default behavior).
As documentation states
If true, any errors for this field will be passed to the parent field or form. For example, if set to true on a normal field, any errors for that field will be attached to the main form, not to the specific field.
Particularly for ChoiceType
Set that error on this field must be attached to the field instead of the parent field (the form in most cases).
Second, you should add error to specific form field
$form
->get('maxRedemptionForDiscountValue')
->addError(new FormError('error message'));
Third, you should edit your template
<div id="maxRedemptionForDiscountValue">
{{ form_errors(form.maxRedemptionForDiscountValue) }}
{{ form_row(form.maxRedemptionForDiscountValue) }}
</div>