3 select in a form with Symfony - forms

(sorry for my english...)
I need your help for my 3 selects in one form.
Select 1: I choose Pays
Select 2: I choose Regions who depend for the Pays
Select 3 : I choose Towns who depends Region
Actually I use javascript in Twig template to have options in the different select, but when I submit the Form, I doesn't have a value for the ville parameter in my object.
Here is my code for ville in the Form:
->add('ville', ChoiceType::class, [
'label' => 'Ville:',
'required' => true,
])
dd($partenaire)
console detail select after query
I have do with EntityType, but this load all the table...
Can someone help me ?
Tanks

I think you should add 2 new routes which return html, specifically the select HTML element with the data from the selected parent, ex:
#[Route('/regions-select', name: 'regions_select', methods: ['GET'])]
public function getRegionsSelect(Request $request): Response
{
$entity = new Entity();
$form = $this->createForm(
FooFormType::class,
$entity,
['pay' => $request->query->get('pay')]
);
return $this->render('_regions-select.html.twig', [
'form' => $form->createView(),
]);
}
Then the Form can look like this:
$builder
->add('district', EntityType::class, [
'placeholder' => 'Select Pay',
'label_attr' => ['class' => 'mb-0 d-block'],
'class' => Pay::class,
'choice_value' => 'id',
'choice_label' => 'name',
])
->add('region', EntityType::class, [
'class' => Region::class,
'query_builder' => function (RegionRepository $regionRepository) use ($options) {
return $regionRepository->regionsByPay((int) $options['pay']);
},
'choice_label' => 'name',
'choice_value' => 'id'
]);
You can create the twig file to render the form row for the regions select '_regions-select.html.twig':
{{ form_row(form.region, {
attr: {
'class': 'mb-3 form-control'
}
}) }}
And you can achieve this by listening to the change event or select event on the Pays dropdown via javascript like this:
$paySelect.on('change', (event) => {
const payId = event.target.value;
$.ajax({
url: BASE_URL+'/regions-select',
data: {
pay: payId,
},
success: function (html) {
const region = REGION_SELECT_FROM_CLASS_NAME //replace this with your jQuery/Javascript selector;
region.html($(html).find("option"));
region.val("").trigger("change");
},
});
});

Related

SYMFONY FormTypeCollection with various fields

In my project I would like to be able to add a Collection on a Form. I thought about the FormTypeCollection. But the thing is, I need something like that:
A "New" button, at the end of the form and everytime you click on the new, a "mini-form" is added and you have the three input to fill: "name,text,link". I would like it to be stored in the database as artists = [name,text,link] for example. I have no idea how to do that. i don't want to add an Entity Artist because I just need this for display and I don't need it to be stored as an Entity on the database.
My code right now is like that:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Contenu')
->add('published', CheckboxType::class, ['required' => false, 'label' => 'Publier'])
->add('title', TextType::class, ['required' => true, 'label' => 'Titre'])
->add('marketingEtiquette', TextType::class, ['required' => false, 'label' => 'Etiquette Marketing'])
->add('textLink', TextType::class, ['required' => true, 'label' => 'Texte du lien'])
->add('shoppingLink', TextType::class, ['required' => true, 'label' => 'Lien'])
->add('media', ElFinderType::class, array(
'label' => 'Photo',
'instance' => 'form',
'enable' => true,
'required' => true,
'attr' => array('class' => 'form-control')
)
)
->add('position',ChoiceType::class, array(
'label' => 'Position dans la page',
'choices' => array(
'Bloc Artistes' => 'artists',
'Bloc haut de page' => 'top',
'Bloc bas de page' => 'bottom'
)
))
->add('artists',CollectionType::class,array(
'label' => 'Les artistes',
'allow_add' => true,
))
->end();
}
I don't know how to add 3 fields to the field artists and generate them on the add button click. i don't even know if it's possible actually. I also don't know what should be the type 'artists' in the database.
EDIT:
I would have like to do something similar to that, so I don't need to create an Entity nor a FormType:
->add('artists',CollectionType::class,array(
'entry_type' => TextType::class ,
'entry_options' => [
'artistName' => TextType::class,
'artistText' => TextType::class,
'artistLink' => TextType::class,
],
'label' => 'Les artistes',
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false
))
But it's not working so I guess I can't. Error:
The current field `artists` is not linked to an admin. Please create one for the target entity : ``
EDIT 2:
I created my ArtistFormType:
class ArtistFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('artistName', TextType::class, array(
'label' => 'Nom de l\'artiste'
))
->add('artistText', TextType::class, array(
'label' => 'Texte sous l\'artiste'
))
->add('artistLink', TextType::class, array(
'label' => 'Lien vers l\'artiste'
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
]);
}
}
I called it like that:
->add('artists',CollectionType::class,array(
'entry_type' => ArtistFormType::class,
'label' => 'Les artistes',
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false
))
But I get the same error:
The current field `artists` is not linked to an admin. Please create one for the target entity : ``
EDIT : This solution is limited to Symfony\Component\Form\Extension\Core\Type\CollectionType, it might be different with the one from Sonata Admin.
You can find some information on this in the documentation.
The "easiest" way to do that, is to create another form (ArtistFormType for example) with the fields you wish to add.
Then in your parent form you add the CollectionType :
$formMapper
// ...
->add('artists', CollectionType::class, [
'entry_type' => ArtistFormType::class,
'label' => 'Artists',
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false
])
;
Then if you already have some artists in your entity it will render the ArtistFormType once for each artist.
If you want to add new artists it is a bit trickier and requires some Javascript.
First, render the collection inside an <ul></ul> tag :
<ul class="artists">
{{ form_row(form.artists) }}
</ul>
Following this jsfiddle :
Find the collection and add an "add artist" button to it
<script>
var $addArtistLink = $('Add an artist');
var $newLinkLi = $('<li></li>').append($addArtistLink);
jQuery(document).ready(function() {
// Get the ul that holds the collection of artists
var $collectionHolder = $('ul.artists');
// add the "add a tag" anchor and li to the tags ul
$collectionHolder.append($newLinkLi);
// ...
}
</script>
Add the "click" event with some dom manipulations to add new artists :
jQuery(document).ready(function() {
// ...
// count the current form inputs we have (e.g. 2), use that as the new
// index when inserting a new item (e.g. 2)
$collectionHolder.data('index', $collectionHolder.find(':input').length);
$addArtistLink.on('click', function(e) {
// prevent the link from creating a "#" on the URL
e.preventDefault();
// add a new artist form
addArtistForm($collectionHolder, $newLinkLi);
});
});
function addArtistForm($collectionHolder, $newLinkLi) {
// Get the data-prototype explained earlier
var prototype = $collectionHolder.data('prototype');
// get the new index
var index = $collectionHolder.data('index');
// Replace '$$name$$' in the prototype's HTML to
// instead be a number based on how many items we have
var newForm = prototype.replace(/__name__/g, index);
// increase the index with one for the next item
$collectionHolder.data('index', index + 1);
// Display the form in the page in an li, before the "Add an artist" link li
var $newFormLi = $('<li></li>').append(newForm);
// also add a remove button
$newFormLi.append('x');
$newLinkLi.before($newFormLi);
// handle the removal
$('.remove-artist').click(function(e) {
e.preventDefault();
$(this).parent().remove();
return false;
});
}
Then it should work fine. Of course some changes might be done to fit your project (field names, add the remove button on existing artists, ...).

Symfony 4 Search Form by entity type (M:N), results show only fields from form, other missing

I have 2 entities: Worker (id, firstname) and Profession (id, title).
I have some workers with one or more professions.
When I open website I see worker data with all professions from workers. For example:
ID: 2 - Tom - teacher, driver
Next, I created search form where i can choose by entity type some of profession and click search.
After this I see list of workers but some o professions dissapear, I see only this professions what i choose in form. For example when I try search drivers:
ID: 2 - Tom - driver (text: teacher profession dissapear from results)
It should be ID: 2 - Tom - teacher, driver (same like before but list should show only persons with driver profession, but text about rest of profession should be here to read)
Code from search controller:
$repository = $this->getDoctrine()->getRepository(Worker::class);
$form = $this->createForm(WorkerSearchType::class, null, [
'method' => 'GET',
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$professions = $form->get('professions')->getData();
$qb = $repository->createQueryBuilder('w')
->select('w, p')
->leftJoin('w.professions', 'p');
if (isset($professions) && count($professions) > 0) {
$qb->andWhere('p.id IN (:professions)')
->setParameter('professions', $professions);
}
$qb = $qb->getQuery();
}
if (!isset($qb)) {
$qb = $repository->createQueryBuilder('w')
->select('w')
->orderBy("w.created", 'DESC')
->getQuery();
}
Fragment of form type:
$builder
->add('professions', EntityType::class, array(
'class' => Profession::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.name', 'ASC');
},
'choice_label' => 'name',
'multiple' => true,
'expanded' => false,
'required' => false,
'label' => false,
));

Empty option in a form query symfony 3.4

I must display an entity in a query_builder form
here is my code in the form type:
$builder->add('dispositif', EntityType::class, array(
'class' => 'LeaPrestaBundle:EgwDispositif',
'label' => 'nomDispositif',
'required' => true,
'empty_data' => null,
'query_builder' => function( $er)
{
return $er->createQueryBuilder('d')
->where('d.isActive = :isActive')
->setParameter('isActive', 1 )
->orderBy('d.nomDispositif','ASC');
},
));
The problem is that the option is empty :
<select id="egw_presta_dispositif" name="egw_presta[dispositif]">
<option value="52"></option>
<option value="55"></option>
<option value="62"></option>
<option value="58"></option>
</select>
For example, aside the value 52, there should have a label for "dispositif" (name of dispositif).
Does it coming from the entity ?
Thanks in advance for your help!
Try adding a 'choice_label' property with the EgwDispositif field containing what you want to display:
$builder->add('dispositif', EntityType::class, array(
'class' => 'LeaPrestaBundle:EgwDispositif',
/** label will be displayed next to your form field unless it's a translation key or else **/
'label' => 'Nom du dispositif',
'required' => true,
'empty_data' => null,
/** any field containing what you want to display as option label **/
'choice_label' => 'nomDispositif',
'query_builder' => function( $er)
{
return $er->createQueryBuilder('d')
->where('d.isActive = :isActive')
->setParameter('isActive', 1 )
->orderBy('d.nomDispositif','ASC');
},
));
It seems like you were confusing the option 'label' of the form field property with the option 'choice_label' . You probably want your label to be something user will read (bu maybe not, it's up to you)
take a look here : https://symfony.com/doc/current/reference/forms/types/entity.html

How to set a class attribute to a Symfony form input with an attribut from entity linked

I have in my form a "beds" attribute, an entity linked to another "bedroom".
I would like for each input to add a class with the id of the linked entity "bedroom".
$form->add('beds', EntityType::class, array(
'class' => 'DamiasResaBundle:Bed',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('b')
->orderBy('b.id', 'ASC');
},
'choice_label' => 'id',
'label' => 'lits ',
'multiple' => true,
'expanded' =>true,
'attr' => array(
'class' => function ($bed) {
return $bed->getBedroom()->getId();
}
),
))
I have two problems:
'attr' => array('class'=>'test) return a class attribut in the div containing the input, not a class attribut in the input.
This previous code does not work and returns:
An exception has been thrown during the rendering of a template ("Catchable Fatal Error: Object of class Closure could not be converted to string") in form_div_layout.html.twig at line 358.
Thank you for your help
I see you are using checkboxes.
Your code seems ok, and since you use query_builder, the values should be a Bed Entity. Note that attr is not mentioned in the EntityType documentation, and I think you need to use choice_attr instead.
Can you try this. I'm not sure if it will work or not:
$form->add('beds', EntityType::class, array(
'class' => 'DamiasResaBundle:Bed',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('b')
->orderBy('b.id', 'ASC');
},
'choice_label' => 'id',
'label' => 'lits ',
'multiple' => true,
'expanded' =>true,
'choice_attr' => function ($val) {
return ['class' => $val->getId()];
},
))
Let us know the results.
You need to customize form rendering
Previous code doesn't work because you're trying to pass Closure object instead of string value. attr array is used as field attributes, so it must contain only string values (or objects with __toString() method).
For EntityType it would rather look like this:
$form->add('beds', EntityType::class, array(
'class' => 'DamiasResaBundle:Bed',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('b')
->orderBy('b.id', 'ASC');
},
'choice_label' => 'id',
'label' => 'lits ',
'multiple' => true,
'expanded' =>true,
'choice_attr' => function (Bed $bed, $key, $index) {
return ['class' => $bed->getBedroom()->getId();];
},
))
Since choice_attr seems not to be working anymore, I am writing another solution. I wasn't able to set attribute (exactly "min") directly from formBuilder. I managed to add it with help of js. I simply searched element by ID given by formBuilder and added atribute.
Inspect your form in browser element inspector and find id.
<div id="form_deadLine">
<input type="date" id="form_deadLine_date" name="form[deadLine][date]" required="required" value="2020-02-20"/>
</div>
Id you wanna look for in my case is form_deadLine_date.
Then you wanna connect .js file to you twig template and write there simple script.
const form = document.getElementById('form_deadLine_date');
if(form){
form.setAttribute("min", "2020-01-02")
}
then my code looks like:
<div id="form_deadLine">
<input type="date" id="form_deadLine_date" name="form[deadLine][date]" required="required" value="2020-02-20"/>
</div>

Symfony2 Form entity field with query_builder

I have a form with an entity field, without the query_builder work fine, but with the query_builder the form display the result of the query but is not valid when is submited.
//tecnicosType
$builder->add('dt', 'entity', array(
'class' => 'MSKLigaBundle:Jugadores',
'label' => 'DT',
'query_builder' => function(
\MSK\LigaBundle\Entity\JugadoresRepository $er) use($equipoId){
return $er->getJugadores($equipoId);
},
'property' => 'nombreCompleto',
'empty_value' => "Sin definir",
'required' => false
))
And the function is
public function getJugadoresQueryBuilder($equipo)
{
$queryBuilder = $this->createQueryBuilder('j');
return $queryBuilder->select('j')
->where('j.equipo_id = :equipo')
->setParameter('equipo', $equipo);
}
when the form is submited return
array
'dt' =>
array
0 => string 'This value is not valid.'
If i coment the query_builder the form validate fine.
I can't find the solution, thank for any help.