Hi,
i have created a search form using GET method, to my indexAction, the form contains virtual fields.
i created the logic for searching inside the indexAction.
My problem is when i submit the form, all inputs values become empty.
What i want is to keep the values passed as arguments in form inputs
here is my FormType :
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('title', TextType::class, array(
'required' => false,
'attr' => array(
'placeholder' => 'Chercher',
)
))
->add('client', EntityType::class, array(
'required' => false,
'class' => 'AppBundle:Person',
'placeholder' => 'Choisir client',
'attr' => array(
'class' => 'select2',
)
))
->add('date_start', DateTimeType::class, array(
'required' => false,
'input' => 'datetime',
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
'inherit_data' => true,
'attr' => array(
'name' => 'date_start',
'class' => 'datepicker',
'placeholder' => 'Date début',
'value' => ''
)
))
->add('date_end', DateTimeType::class, array(
'required' => false,
'input' => 'datetime',
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
'inherit_data' => true,
'attr' => array(
'name' => 'date_end',
'class' => 'datepicker',
'placeholder' => 'Date fin',
'value' => ''
)
))
;
}
The indexAction :
public function indexAction(Request $request)
{
$getArgs = $request->query->get('order');
dump($getArgs);
$form = $this->createForm('AppBundle\Form\Search\OrderType', new Order(), array('get' => $getArgs));
$form->handleRequest($request);
$repo = $this->getDoctrine()->getRepository('AppBundle:Order');
$query = $getArgs ? $repo->findAllMatched($q) : $repo->createQueryBuilder('o');
$paginator = $this->get('knp_paginator');
$orders = $paginator->paginate($query);
return $this->render('AppBundle:Order:index.html.twig', array(
'orders' => $orders,
'form' => $form->createView(),
));
}
Any suggestions are wellcome.
For now, i resolved the problem in this way :
<div class="nav box-search">
<form method="GET" class="form-inline">
<div class="pull-right">
<button type="submit" class="btn btn-default">{{ 'actions.search' | trans }}</button>
</div>
<div class="pull-left">
{% set params = app.request.query.all %}
{{- form_widget(form.title, { 'attr': {'value': params.order.title| default('')} }) -}}
{{ form_widget(form.client, {value: params.order.client| default('') }) }}
{{- form_widget(form.date_start, { 'attr': {'value': params.order.date_start| default('')} }) -}}
<i class="fa fa-exchange"></i>
{{- form_row(form.date_end, { 'attr': {'value': params.order.date_end| default('')} }) -}}
</div>
</form>
</div>
It's not that bad solution, but what i would is to have this parameters configuration in the FormType.
Related
I'm trying to make a form to add an entity in my database (a project). I realized exactly the same thing for other entities, everything works, but for this one (a project), it does not work ...
Screen of error : http://image.noelshack.com/fichiers/2019/02/1/1546884788-capture.png
ProjectController :
/**
* #Route("/projects/add", name="add_projects")
*/
public function addProject(Request $request)
{
$em = $this->getDoctrine()->getManager();
$project = new Project();
$form = $this->createForm(AddProjectType::class, $project);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($project);
$em->flush();
return $this->redirectToRoute('index_projects');
}
return $this->render('/project/add.html.twig', [
'form' => $form->createView(),
]);
}
AddProjectType :
class AddProjectType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, array(
'attr' => array(
'placeholder' => 'Nom',
),
'label' => false,
))
->add('price', IntegerType::class, array(
'attr' => array(
'placeholder' => 'Prix',
),
'label' => false,
))
->add('type', ChoiceType::class, array(
'choices' => array(
'Application web' => 'Application web',
'Site internet' => 'Site internet',
'Application mobile' => 'Application mobile',
'Autre' => 'Autre',
),
'label' => false,
))
->add('client', EntityType::class, array(
'class' => User::class,
'choice_label' => function($user) {
return $user->getUsername();
},
'label' => false,
))
->add('state', ChoiceType::class, array(
'choices' => array(
'A faire' => 'A faire',
'En cours' => 'En cours',
'Terminé' => 'Terminé',
),
'label' => false,
))
->add('description', TextareaType::class, array(
'attr' => array(
'placeholder' => 'Description',
),
'label' => false,
))
->add('Ajouter', SubmitType::class, [
'attr' => [
'class' => 'btn btn-success',
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Project::class,
]);
}
}
add.html.twig :
{% extends "./base.html.twig" %}
{% block title %}{{ parent() }}Ajouter un projet{% endblock %}
{% block stylesheets %}
{{ parent() }}
<style>
form input, form select, form textarea {
width: 100%;
margin: .5em 0;
}
</style>
{% endblock %}
{% block body %}
{{ parent() }}
<h1 class="title-page">Ajouter un projet</h1>
<div class="container-fluid">
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</div>
{% endblock %}
Did you look into the database whether the project is added?
In your controller I don't see a reason for a ParamConverter, therefore I guess that the error happens after the redirect to index_projects
I just managed to find out why I had this error, I'll post the salution here so that other people have it:
I had in this controller a route /projects/{id} (to access the details of a project), I modified it by /projects/details/{id}
Is it possible to change those numbers (names of embedded forms) to some other labels (they depend on StatisticField's name property) without using javascript?
StatisticType has StatisticFieldTypes:
$builder->add('statisticFields', CollectionType::class, array(
'entry_type' => StatisticFieldType::class,
'by_reference' => true,
));
StatisticFieldType:
$builder->add('dateSince', DateTimeType::class, [
'widget' => 'single_text',
'label' => 'date.since',
'required' => false,
])
->add('dateTo', DateTimeType::class, [
'widget' => 'single_text',
'label' => 'date.to',
'required' => false,
]);
Thanks.
[EDIT_1]:
My template:
<h1>Statistic creation</h1>
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="submit" value="Create"/>
{{ form_end(form) }}
Try
$builder->add('statisticFields', CollectionType::class, array(
'entry_type' => StatisticFieldType::class,
'entry_options' => array('label' => false),
'by_reference' => true,
));
The numbers came from CollectionType
EDIT:
With Names
$name = 'IamNotANumber';
$builder->add('statisticFields', CollectionType::class, array(
'entry_type' => StatisticFieldType::class,
'entry_options' => array('label' => $name),
'by_reference' => true,
));
The solution was to override buildView method in StatisticFieldType (embedded form type) and get the data from the form :
/**
* {#inheritDoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
// For Symfony 2.1 and higher:
$view->vars['label'] = $form->getData()->getName();
}
I have a form that has to contain a choice field which displays its content from another entity (not the entity used in the form), so this is how I tried to create it:
$user = new user();
$profils=$rep->findAll();
$form2 = $this->createFormBuilder($user,array('csrf_protection' => false))
->add('id', 'text',array('attr'=>array("autocomplete" => "off",'name'=>'login_user','required'=>'required',
'maxlength'=>'255','placeholder'=>'Matricule')))
->add('password', 'password',array('attr'=>array('autocomplete' => 'off','placeholder'=>'Mot de passe','required'=>'required')))
->add('profils', 'choice',[
'choices' => [$profils]],array('attr'=>array('mapped'=>false,'required'=>'required')))
->add('Ajouter', 'submit', array('attr' => array('class' => 'btn btn-primary btn-block rounded_btn', 'id' => 'login_btn',
'style' => "width:6vw;height:5vh;padding:0px 0px; position:relative;left:5vmin;top:1vmin;font-size:2vmin;")))
->getForm();
Pleaaaase help me, as I'm new with symfony, I may be stuck in problems you may consider stupid, I'm sorry but i couldn't find a solution myself.
I fixed it by changing the place of "'mapped'=>false" and it worked:
$form2 = $this->createFormBuilder($user,array('csrf_protection' => false))
->add('id', 'text',array('attr'=>array("autocomplete" => "off",'name'=>'login_user','required'=>'required',
'maxlength'=>'255','placeholder'=>'Matricule')))
->add('password', 'password',array('attr'=>array('autocomplete' => 'off','placeholder'=>'Mot de passe','required'=>'required')))
->add('profils', 'choice'
,array( 'choices' => array('Profils' => $profArr),'mapped'=>false),
array('attr'=>array('required'=>'required')))
->add('Ajouter', 'submit', array('attr' => array('class' => 'btn btn-primary btn-block rounded_btn', 'id' => 'login_btn',
'style' => "width:6vw;height:5vh;padding:0px 0px; position:relative;left:5vmin;top:1vmin;font-size:2vmin;")))
->getForm();
One way of doing it is this :
In the repository of profil entity create a method eg that return an array of profils e.g
class ProfilRepository extends EntityRepository
{
public function myFindAll()
{
$queryBuilder = $this->createQueryBuilder('p');
$entites = $queryBuilder->getQuery()->getArrayResult();
return $entites;
}
}
In the controller as you are doing now,
$user = new user();
// I'm asuming that Profil is an entity
$profils = $this
->getDoctrine()
->getManager()
// this should return an array
->getRepository('SdzBlogBundle:Profil')->myFindAll()
;
$form2 = $this->createFormBuilder($user, array('csrf_protection' => false))
->add('id', 'text', array(
'attr' => array(
'autocomplete' => 'off',
'name' => 'login_user',
'required' => 'required',
'maxlength' => '255',
'placeholder' => 'Matricule'
)
))
->add('password', 'password', array(
'attr' => array(
'autocomplete' => 'off',
'placeholder' => 'Mot de passe',
'required' => 'required'
)
))
->add('profils', 'choice', array(
'choices' => $profils,
array(
'attr' => array(
'mapped' => false,
'required' => 'required'
)
)
))
->add('Ajouter', 'submit', array(
'attr' => array(
'class' => 'btn btn-primary btn-block rounded_btn',
'id' => 'login_btn',
'style' => "width:6vw;height:5vh;padding:0px 0px; position:relative;left:5vmin;top:1vmin;font-size:2vmin;"
)
))
->getForm()
;
That's all for now, Good luck.
I am building a form using the formbuilder, where I need to add <hr/> after certain fields. How can I do that? FYI, Need to add <hr/> after the field priority and another before biography. My form builder:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text',
array(
'label' => 'Name English',
))
->add('bangla_name','text',
array(
'label' => 'Name Bangla',
'required' => false
))
->add('real_name','text',
array(
'required' => false
))
->add('debut', 'text',array(
'label' => 'Debut Film',
'required' => false))
->add('birth_place','text',array(
'label'=> 'Birth Place',
'required' => false
))
->add('sex', 'choice', array(
'choices' => array('M' => 'Male', 'F' => 'Female', 'N/A' => 'N/A'),
'row_attr' => array(
'class' => 'col-sm-6 n-p-l'),
'label'=> 'Sex',
'label_attr' => array(
'class' => 'col-md-4'
),
))
->add('priority','choice', array('required' => true, 'label'=> 'Priority','attr'=> array('class'=>'col-md-2'), 'choices' => array(
'0' => '0',
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4'
), 'row_attr' => array(
'class' => 'col-sm-4'
),
'label_attr' => array(
'class' => 'col-md-6'
),
))
->add('bday','choice',
array(
'required' => true, 'choices' => $this->buildDayChoices(),'label'=> 'Birth Day',
'row_attr' => array(
'class' => 'col-sm-4 n-p-l'),
'help' => '*required',
'label_attr' => array(
'class' => 'col-md-6'
)
))
->add('bmonth','choice',
array(
'required' => true, 'choices' => $this->buildMonthChoices(),'label'=> 'Birth Month',
'row_attr' => array(
'class' => 'col-sm-4 n-p-l'),
'help' => '*required',
'label_attr' => array(
'class' => 'col-md-6'
),
))
->add('byear','choice',
array(
'required' => true, 'choices' => $this->buildYearChoices(),'label'=> 'Birth Year',
'row_attr' => array(
'class' => 'col-sm-4 n-p-l'),
'help' => '*required',
'label_attr' => array(
'class' => 'col-md-6'
),
))
->add('dod_day','choice',
array(
'required' => true, 'choices' => $this->buildDayChoices(),'label'=> 'Death Day',
'row_attr' => array(
'class' => 'col-sm-4 n-p-l'),
'help' => '*required',
'label_attr' => array(
'class' => 'col-md-6'
),
))
->add('dod_month','choice',
array(
'required' => true, 'choices' => $this->buildDayChoices(),'label'=> 'Death Month',
'row_attr' => array(
'class' => 'col-sm-4 n-p-l'),
'help' => '*required',
'label_attr' => array(
'class' => 'col-md-6'
),
))
->add('dod_year','choice',
array(
'required' => true, 'choices' => $this->buildDayChoices(),'label'=> 'Death Year',
'row_attr' => array(
'class' => 'col-sm-4 n-p-l'),
'help' => '*required',
'label_attr' => array(
'class' => 'col-md-6'
),
))
// ->add('birth','birthday', array('label' => 'Date of Birth', 'years' => range(1950, date('Y')-10)))
->add('bio_english','textarea',array(
'label'=> 'Biography - English',
))
->add('bio_bangla','textarea',array(
'label'=> 'Biography - Bangla',
))
->add('graphics', 'graphics', array(
'upload_directory' => 'uploads' . DIRECTORY_SEPARATOR . 'artist','row_attr' => array(
'class' => 'col-sm-12')
))
;
}
I don't think you can. A horizontal rule is not a form construct, and as such, has no business being defined by a FormBuilder.
This needs to be handled in the view/template
{{ form_row(form.priority) }}
<hr/>
{{ form_row(form.bday) }}
IMO, you've been a bit too liberal with your use of the HTML properties in your builder. Those should be used only if you really need them. Again, they are primarily view concerns.
EDIT
You can add this customization in the form's view, and override the form_row block to be aware of this customization
src/AppBundle/Form/YourFormType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
class YourFormType extends AbstractType
{
/* ... Rest of form type ... */
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view['priority']->use_separator = true;
parent::buildView($view, $form, $options);
}
}
Then the form block
{% block form_row %}
{{ parent() }}
{% if form.use_separator is defined %}
<hr/>
{% endif %}
{% endblock %}
All right, as I said in comments, one way would be to override specific field of your form. If you are interested in the subject, you can read more here.
For the purpose of demonstrating, I've created simple form with 3 fields, as follows:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('username', 'text');
$builder->add('email', 'email');
$builder->add('password', 'password');
}
Now, the important part here is the name of the form (it's used later when overriding)
public function getName() {
return 'myform';
}
Nothing new here, most of the magic happens in your template file.
{% form_theme form _self %}
The following line tells Symfony that you are using the same template file as a base to create a form theme. Next:
{% block _myform_email_row %}
{{ block('form_row') }}
<hr/>
{% endblock %}
This block is all you need to define at the top of your template, after {% form_theme ... %}
{% block _myform_email_row %}
_myform is the name of your form obviously.
_email is the name of the input you want to override
_row is what part of it you want to override. row stands for label, widget and block. _widget would override only the part that renders the input.
And that's all you need. Define custom block, render the default block and add <hr/> at the end of it. You can override any template part like that.
Edit - response to a comment
but can't exactly use it because I can't use {% form_theme form _self %}
You can delete the whole {% form_theme %} line and move your custom {% block _myform_... %} to separate template. Then open your config.yml, look for the section twig and include the template as a resource, like this:
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
form:
resources:
- theme/custom.html.twig
Here my template is located in app/Resources/views/theme
This will include your template in every form you have. But since you override specific field of specific form, it should not interact with other forms. This way would save you the trouble of using {% form_theme %} block.
I have a form, SiteType, with an other form, DomainType, embbed. But when I tried to display in the site form the domain name field, which is a choice list, it appears 3 times (each list contains all the domains in the DB) instead of one time.
This is my SiteType :
class SiteType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array(
'label' => 'Nom du site',
'required' => true
))
->add('nameBundle', 'text', array(
'label' => 'Nom du bundle du site',
'required' => true
))
->add('numClient', 'integer', array(
'label' => 'Numéro client du site',
'required' => true
))
->add('domains', 'collection', array(
'type' => new DomainType(),
));
}
...
}
and my DomainType:
class DomainType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('domainName','entity', array(
'class' => 'EliophotBackBundle:Domain',
'property' => 'domainName',
'label' => 'Nom du domaine'
));
}
...
}
and the form where I display the form :
<form action="{{ path('site_create') }}" method="post">
{{ form_row(form.name) }}
{{ form_row(form.nameBundle) }}
{{ form_row(form.numClient) }}
{% for domain in form.domains %}
{{ form_row(domain.domainName) }}
{% endfor %}
{{ form_rest(form) }}
<div class="btn-group">
<button type="submit" class="btn btn-success">Ajouter</button>
</div>
</form>
My SiteController :
public function newSiteAction()
{
$site = new Site();
$repository = $this->get('doctrine')
->getRepository('TestBackBundle:Domain');
$domains = $repository->findAll();
foreach($domains as $domain) {
$domainObject = new Domain();
$domainObject->setDomainName($domain->getDomainName());
$site->getDomains()->add($domainObject);
}
$newForm = $this->createForm(new SiteType(), $site);
return $this->render('TestBackBundle:Site:new_site.html.twig', array(
'site' => $site,
'form' => $newForm->createView(),
));
}
I would like to diplay only one choice list with all the domains name... How can I do this ?
I think you can resolve this like this:
SiteType
$builder
->add('name', 'text', array(
'label' => 'Nom du site',
'required' => true
))
->add('nameBundle', 'text', array(
'label' => 'Nom du bundle du site',
'required' => true
))
->add('numClient', 'integer', array(
'label' => 'Numéro client du site',
'required' => true
))
->add('domains','entity', array(
'class' => 'EliophotBackBundle:Domain',
'property' => 'domainName',
'label' => 'Nom du domaine',
'multiple' => true
));
In this case you wouldn't have need for DomainType. As for the controller can you clarify this snippet:
$domains = $repository->findAll();
foreach($domains as $domain) {
$domainObject = new Domain();
$domainObject->setDomainName($domain->getDomainName());
$site->getDomains()->add($domainObject);
}
Why are you fetching and then reconstructing all the domains? Are the domains from Site entityt not of type TestBackBundle:Domain? If they are in fact, you could just:
$domains = $repository->findAll();
$site->setDomains(new ArrayCollection($domains)); // don't forget sto `use` ArrayCollection
Hope this helps a bit...