symfony search form keep seach parameters - forms

I made a searchform, but i don't know how to keep the selected search parameters in the form.
I would like to do this through the controller and not in twig file self.
I thought by setting the parameter it will preselect the option but that doesn't work.
Below my form
$builder
->add('type', EntityType::class, [
'class' => Producttype::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('p')
->orderBy('p.id', 'ASC');
},
'choice_label' => 'Title',
'placeholder' => 'All types',
'required' => false,
])
->add('Search', SubmitType::class)
;
}
In the controller I have this
$query = $request->query->get('searchfilter');
$querybuilder = $em->getRepository(Product::class)
->createQueryBuilder('p');
if($query['type'] != NULL) {
$querybuilder->innerJoin('p.producttype', 'b')
->addSelect('b')
->andWhere('b.id like :type')
->setParameter('type', $query['type']);
;
}
and the form in twig
<div class="container">
{{ form_start(form, {'action': path('product_search'), 'method': 'GET'}) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</div>
Thanks in advance!

Related

Symfony form not valid and not submittable

When trying to submit my form, it is not working. The button is not doing anything at all. So I tried to dump something withing my:
if ($form->isValid() && $form->isSubmitted())
And realized that it's not even entering the if statement, so I assume that there is something wrong with my form. But I can't yet figure out what it would be, so I would be glad if anyone could help me!
/**
* #Route("/document/bulkdeactivate", name="documentBundle_document_bulkDeactivate")
* #Template()
*/
public function bulkDeactivateAction(Request $request) {
$em = $this->getDoctrine()->getManager();
$selected_documents = $request->request->all();
$form = $this->createForm(DocumentDeactivationType::class);
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted()) {
foreach($selected_documents as $document) {
$documentR = json_decode(json_encode($document), true);
dump($documentR);
for($i=0; $i<count($documentR); $i++){
$doc = $em->getRepository('DocumentBundle:Document')->findOneById($documentR[$i]);
dump($doc);
$doc->setActive(false);
$em->persist($doc);
$em->flush();
}
}
$this->addFlash(
'success',
'The document has been deactivated!'
);
return $this->redirectToRoute('documentBundle_document_list');
}
return $this->render('DocumentBundle:Panels:ActivationPanel.html.twig', array(
'form' => $form->createView(),
));
}
my Form Type:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('documentlist', EntityType::class, array(
'class' => 'DocumentBundle:Document',
'choice_label' => 'name',
'required' => false,
'multiple' => true,
'expanded' => false,
'placeholder' => "Select Documents",
'label' => 'label.document_list',
))
->add('submit', SubmitType::class, array(
'label' => 'Submit',
'attr' => array(
'class' => 'btn btn btn-default',
),
));
}
And the form part of my twig template:
{% block content %}
{{ form_start(form) }}
{{ form(form.documentlist) }}
{{ form(form.submit) }}
{{ form_end(form) }}
{% endblock content %}
There must be some issues with the form, do you have any advice for my?
Actually there are several issues:
you cannot add a submit button that is not bound to a Symfony form in your case because Symfony will not identify it properly (for lack of a name that has to match SF's automatic input names generation)
In your formBuilder put:
$builder->add('submit', SubmitType::class);
your form has an incorrect name ("form") that conflicts with Twig's form() function, you have to change it,
you might have an issue (not tested, just a guess) regarding the many calls made to Twig's form() because this function dumps the whole form content, to manually dump each part use
Your {% block content %} should have this:
{{ form_widget(form.your_widget_name, attrs) }}
I eventually solved my issue:
1. as pointed out by #NaeiKinDus, I needed a Submit button that actually belonged to my form, plus I changed my form name to a custom deactivationForm
{% block content %}
{{ form(deactivationForm) }}
{% endblock content %}
the buildForm method:
$builder
->add('documentlist', EntityType::class, array(
'class' => 'DocumentBundle:Document',
'choice_label' => 'name',
'required' => false,
'multiple' => true,
'expanded' => false,
'placeholder' => "Select Documents",
'label' => 'label.document_list',
'translation_domain' => 'Documents',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('d')
->where('d.active = FALSE');
},
))
->add('submit', SubmitType::class, array(
'label' => 'Submit',
'attr' => array(
'class' => 'btn btn btn-default',
),
));
then in my controller:
/**
* #Route("/document/bulkdeactivate", name="documentBundle_document_bulkDeactivate")
* #Template()
*/
public function bulkDeactivateAction(Request $request) {
/*
* GET DOCUMENT FROM DB
*/
$em = $this->getDoctrine()->getManager();
$selected_documents = $request->request->all();
$deactivationForm = $this->createForm(DocumentDeactivationType::class);
$deactivationForm->handleRequest($request);
if ($deactivationForm->isValid() && $deactivationForm->isSubmitted()) {
foreach($selected_documents as $document) {
$documentR = json_decode(json_encode($document), true);
dump(count($documentR['documentlist']));
for($i=0; $i<count($documentR['documentlist']); $i++){
$doc = $em->getRepository('DocumentBundle:Document')->findOneById($documentR['documentlist'][$i]);
dump($documentR['documentlist'][$i]);
$doc->setActive(true);
$em->persist($doc);
$em->flush();
}
}
$this->addFlash(
'success',
'The selected document(s) have been deactivated!'
);
return $this->redirectToRoute('documentBundle_document_list');
}
return $this->render('DocumentBundle:Panels:ActivationPanel.html.twig', array(
'deactivationForm' => $deactivationForm->createView(),
));
}
I tried to access the wrong array positions (I didn't realize that the decoding of the ajax data sent me 3 array positions but I only wanted to access the first 'documentlist' and then get the document IDs from that one.

Symfony2 - NotBlank constraint not working on EntityType

I have two EntityType fields in my form and both has NotBlank constraint assigned to them.
Now, I have this issue that NotBlank constraint is not working only on one field with multiple => true set on.
$builder
->add('preferredCountries', EntityType::class, array(
'required' => false,
'class' => 'IndexBundle:Country',
'property' => 'name',
'empty_value' => 'Choose',
'multiple' => true,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.name != :name')
->orderBy('c.name', 'ASC')
->setParameter('name', 'Other');
},
'constraints' => array(
new NotBlank(array(
'message' => 'blank!!!',
)),
)
))
->add('internshipProgram', EntityType::class, array(
'required' => false,
'class' => 'IndexBundle:InternshipProgram',
'property' => 'name',
'empty_value' => 'Choose',
'constraints' => array(
new NotBlank(array(
'message' => 'blank!!!',
)),
)
))
In this case when I submit empty values, field internshipProgram get an error, and prefferedCountries not.
Form display:
<div class="form-group col-xs-12">
{{ form_label(current_internship_form.preferredCountries, 'Preferred countries', { 'label_attr': {'class': 'label-text'} }) }}
{{ form_widget(current_internship_form.preferredCountries) }}
<span class="error text-danger small">{{ form_errors(current_internship_form.preferredCountries) }}</span>
</div>
<div class="form-group col-xs-12">
{{ form_label(current_internship_form.internshipProgram, 'What type of training agreement will you have?', { 'label_attr': {'class': 'label-text'} }) }}
{{ form_widget(current_internship_form.internshipProgram, { 'id': 'internship_program', 'attr': {'class': 'form-control '}}) }}
<span class="error text-danger small">{{ form_errors(current_internship_form.internshipProgram) }}</span>
</div>
Is there a mistake in my code or is it somehow related to multiple choice selection? Has anyone had similar issue and know how to solve it?
You can't use NotBlank constraint on EntityType with multiple set to true. As the array will never be null. You should try using the count constraint like this:
$builder
->add('preferredCountries', EntityType::class, array(
'required' => false,
'class' => 'IndexBundle:Country',
'property' => 'name',
'empty_value' => 'Choose',
'multiple' => true,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.name != :name')
->orderBy('c.name', 'ASC')
->setParameter('name', 'Other');
},
'constraints' => array(
new Count(array(
'min' => 1,
'minMessage' => "Should not be blank"
))
)
))
...
Also you can specify at Entity level,
/**
* #Count(min = 1, minMessage = "At least one branch must be selected")
*/
protected $multiCheckBox;

Symfony2 : Change {{ form_enctype }} to {{ form_start }} with a custom path

I'm working on updating my code to Symfony3 standards but I come to some problems with some of my forms. I tried several things but nothing is working.
In my twig :
<form action="{{ path('paces_colle_gestioncsv_imprimer',
{ 'id' : document.id }) }}" method="post" {{ form_enctype(form) }}>
</form>
{{ form_enctype }} is deprecated since Symfony 2.8. I have to get the path to the controller to change it to {{ form_start }}
In my controller :
public function ajouterErrataAction($id)
{
$em = $this->getDoctrine()->getManager();
$document = $em->getRepository('PACESColleBundle:DocumentCSV')->find($id);
if(!$document){
throw $this->createNotFoundException('Document inexistant');
}
$colle = $document->getColle();
$form = $this->createForm(ajouterErrataType::class);
return $this->render('PACESColleBundle:Classement:ajouterErrata.html.twig', array(
"colle" => $colle,
"document" => $document,
"form" => $form->createView()
));
}
My formType :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('errata', TextareaType::class, array('required' => false,
'attr' => array('class'=>'ckeditor')
))
->add('precision', TextareaType::class, array('required' => false,
'attr' => array('class'=>'ckeditor')))
->add('submit',SubmitType::class, array('label' => 'Imprimer'));
;
}
You can override action in controller or template:
http://symfony.com/doc/current/book/forms.html#changing-the-action-and-method-of-a-form
Have you tried?
You can set the action path like this:
$form = $this->createForm(ajouterErrataType::class, $data, [
'action' => $this->generateUrl(''paces_colle_gestioncsv_imprimer', ['id' => $document->getId()]),
'method' => 'POST',
]);
The Symfony 3 way of doing it is like this:
$form = $this->createForm(TaskType::class, $task, array(
'action' => $this->generateUrl('target_route'),
'method' => 'GET',
));

Symfony2 form class renders all rows even if I don't want it to

First of all, I am sorry if the question title is a bit odd, but I do not know what else to call it...
I have this form class, which I cannot change:
class ItemDetailType extends AbstractType {
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', 'text', array(
'label' => 'Název'))
->add('room', 'entity', array(
'class' => 'CvutFitIctCtuIdentityBundle:Room',
'label' => 'Místnost'))
->add('person', 'entity', array(
'class' => 'CvutFitIctCtuIdentityBundle:Person',
'label' => 'Osoba'))
->add('organizationalUnit', 'entity', array(
'class' => 'CvutFitIctCtuIdentityBundle:OrganizationalUnit',
'label' => 'Organizační jednotka'))
;
$builder->setAttribute('attr', array());
if (isset($options['render_submit']) && $options['render_submit'])
$builder
->add('submit', 'submit', array(
'label' => 'Uložit',
'attr' => array('class' => 'btn btn-success')))
->add('reset', 'reset', array(
'label' => 'Zrušit',
'attr' => array('class' => 'btn btn-danger')))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Cvut\Fit\BiWt2\InventoryBundle\Entity\Item',
'render_submit' => true,
'attr' => array(
'role' => 'form',
'class' => 'form-horizontal'
)
));
}
/**
* #return string
*/
public function getName() {
return 'cvut_fit_biwt2_inventory_form_item';
}
}
But in a template, I have to render only some of the rows (room, person, organizationalUnit and submit), and not render name and reset. This is in the conditions I am obliged to meet, so editing the class is not a valid option.
In controller I create the form like this:
$form = $this->createForm(
new ItemDetailType, $item, array(
'action' => $this->generateUrl('items_detail_form', array('id' => $id)),
'render_submit' => true
)
);
I tried to render only the desired rows this way, but it only makes the go on top of the form and the remaining two are still rendered under them...
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.room) }}
{{ form_row(form.person) }}
{{ form_row(form.organizationalUnit) }}
{{ form_row(form.submit) }}
{{ form_end(form) }}
So I am a bit confused now. Is this the correct behavior? If yes, than how do I achieve what I need? The documentation is somewhat brief about this...
Thank you very much!
In symfony2 the default behaviour of:
{{ form_end(form) }}
is render all (even not mentioned before) fields like
{{ form_rest(form) }}
If you want to prevent this behaviour the one option is use:
</form>
or the better way like in this document http://symfony.com/doc/current/reference/forms/twig_reference.html#form-end-view-variables
{{ form_end(form, {'render_rest': false}) }}
Remember to render CSRF token manualy if you do this in that way:
{{ form_widget(form._token) }}
what about using
{% do form.name.setRendered %}
{% do form.reset.setRendered %}
This tell twig that the fields are shown even if they aren't
I am confused as to what exactly do you want to achieve here. But here are some thoughts:
You can create a new form type that extends this one if you want.
class ShorterItemDetailType extends ItemDetailType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
// only add the fields you want
}
public function getParent() {
return 'cvut_fit_biwt2_inventory_form_item'
}
/**
* #return string
*/
public function getName() {
return 'cvut_fit_biwt2_inventory_form_item_shorter';
}
}
And in your controller use this one.
$form = $this->createForm(
new ShorterItemDetailType(), $item, array(
'action' => $this->generateUrl('items_detail_form', array('id' => $id))
)
);

Symfony2 form collection with checkboxes

I'm building a form with Symfony2 and need to group some checkboxes. I simply cannot figure out how to pass choices/label along to the checkboxes in BonusGroup.
Form:
$builder->add('groups', 'collection', array(
'type' => new BonusGroup(),
'allow_add' => false,
'allow_delete' => false,
'by_reference' => false
));
BonusGroup():
$builder->add('bonus', 'choice', array(
'choices' => $options['bonus'],
'multiple' => true,
'expanded' => true
));
View.twig:
{% for group in form.groups %}
{{ form_label(group) }}
{% for final in group.bonus %}
{{ form_widget(final) }}
{% endfor %}
{% endfor %}
Passing data to form:
$data = array(
'groups' =>
array ('Group 1 label' => array())
);
$form = $app['form.factory']->createBuilder(new Form(), $data))->getForm();
Any tips?
Thanks!
First, change form_widget to form_row, but it won't work yet because collection type need a piece of JavaScript to work.
See examples here:
http://symfony.com/doc/2.1/reference/forms/types/collection.html