Symfony2 personnalisation every attr radio buttons - symfony

I can not find the opportunity to customize the attributes on radio buttons separately, because I want to insert a title tag and data-toggle="tooltip" to display a tooltip on every radio buttons
$builder
->add('type', 'choice', array(
'choices' => array(
'0' => 'Demande', // Here personnalise attr
'1' => 'Recherche', // Here personnalise attr
),
'expanded' => true,
))
I tried with the attr option, but it puts on all the radio buttons ... Or should that EVERY radio button is a different attr.
Thank you !

The expanded choice list in Symfony is actually a form with children of either type radio or type checkbox (depending on the multiple option being false or true respectively).
In my opinion, the best way to solve this, is create a custom type, and do your own templating of the type. This usually is the most clear to the fellow developer and is consistent (and much easier than you might think).
The type should look like this:
class MyType extends AbstractType()
{
public function getName()
{
return 'tooltip_choice';
}
public function getParent()
{
return 'choice';
}
}
Add this class to your service definitions and tag it as a form type (see docs on this).
Now, the form templating layer will search for a block named tooltip_choice_row (for the row of the element), tooltip_choice_widget for the widget of the element. If you inspect the default form templates, you can easily dissect how the choice list rendering works in the default implementation. You can either copy and paste it to your custom form theming and override.
The downside of this solution is that it costs a little bit more code, but you can much easier extend your types to include the tooltip itself, and pass that as an option to your form type as well.
Another solution would be to override the radio_widget and the checkbox_widget blocks in your form template, and check if the parent is a choice block. You can find out what exact variables you need by dumping the _context variable in your template, it shows exactly what values are available for you to check on.

Related

How can I add a paragraph (as default) in the node form by using hook_form_alter in Drupal 8?

I am trying to add a bunch of different empty paragraphs of different types, to a entity reference revisions field, everytime a node of a certain content type is created.
I DON'T want to use the contrib module "default paragraphs" for this, because I need to use a certain form widget here, and default paragraphs is also achieved by a widget.
What I tried so far:
function myModule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){
$paragraph = \Drupal\paragraphs\Entity\Paragraph::create([
'type' => 'tab_features'
]);
$paragraph->save();
$form['field_tabs']['widget'][0]['target_id']=$paragraph->id();
$form['field_tabs']['widget'][0]['target_revision_id']=$paragraph->getRevisionId();
return $form;
}
$field_tabs is my entity reference revisions field.
'tab_features' is the paragraphs type I want to add.
I guess there should be a method that can be used in the form or form widget to add a paragraph to the form, like someone already clicked the button to add it. I want to avoid to actually trigger this via Javascript if possible. Anybody knows how to do this in form_alter?
In a project I'm working on, we have done something like this:
//get the body field
$field = $entity->get('field_em_p_body');
$paragraph = Paragraph::create([
'type' => 'em_section', // Paragraph type.
]);
$paragraph->isNew();
$paragraph->set('YOUR_FIELD', 'SOMETHING');
$field->appendItem($paragraph);

Set easyadmin_autocomplete Select Null by default. Symfony

I would like to know if there is any way to put null value by default in the easyadmin_autocomplete select.
The first item in the list is selected and filled with data from database but i need a null value by default and setted automaticly. The goal is a first result point to an empty one (Choose one...).
Do you know how to do it?
Can you think of any way combining the options defined below?
#easy_admin.yml
Product:
class: App\Entity\Product
controller: App\Controller\ProductController
new:
fields:
- { property: 'category', label: 'Category', type: 'easyadmin_autocomplete', type_options: { class: 'App\Entity\Category' } }
}
In this example, one select has a placeholder with the text 'Any' (Ninguno). I need to know why is handling them different.
These are the options defined for the attr fields -> type_options of the yml:
action
allow_extra_fields
allow_file_upload
attr
auto_initialize
block_name
by_reference
class
compound
constraints
csrf_field_name
csrf_message
csrf_protection
csrf_token_id
csrf_token_manager
data
data_class
disabled
empty_data
error_bubbling
error_mapping
extra_fields_message
help
help_attr
inherit_data
invalid_message
invalid_message_parameters
label
label_attr
label_format
mapped
method
multiple
post_max_size_message
property_path
required
translation_domain
trim
upload_max_size_message
validation_groups
If setting your default value would be a solution for you (like zero), service listener might be an answer:
// You need to add this listener yourself:
class ProductServiceListener
{
...
// you can manipulate entity in this level as you wish:
public function preUpdate(LifeCycleEventArgs $args)
{
// You will focus to Product entity, so block others:
if (!(get_class($entity) == 'App\Entity\Product')) {
return;
}
// Set whatever default value you want if it's null:
if($entity->getCategory() == null) {
$entity->setCategory(0); // Zero, as an example.
}
There is no way to set a placeholder like value for easyadmin_autocomplete.
The normal way for a choice type is to use the placeholder option as described in the symfony documentation. But easyadmin_autocomplete does not extend that type and it is a standalone type. Can't you use a choice type or entity type with the placeholder option. The only need for the easyadmin_autocomplete type is if there are a lot of entities and it will slow the application if all are loaded on the page.
My best bet is that you can extend the easyadmin_autocomplete. Because the easyadmin_autocomplete uses EntityType you can add the option for placeholder in the configureOptions method in the extended type. That will delegate the option to the EntityType but even then it is not displayed in the html because of the select2 javascript which also needs to be modified.
If it is a must I recommend the way to extend the type, add the option and also add custom javascript to easyadmin that will handle the new type and add the placeholder option. You can see the select2 documentation on how to set the placeholder.
But if you can use the entity or choice type for your select it is the preferred solution.

Render a field multiple times in Twig and Symfony

I need two inputs so that the user can choose from
Controller
$etud = new Etudiant();
$form=$this->createFormBuilder($etud)
->add('filierechoisit',EntityType::class,array('class'=>'inscriptionBundle\Entity\filieres', 'choice_label'=>'libelle_filiere'))
->add('filierechoisit',EntityType::class,array('class'=>'inscriptionBundle\Entity\filieres', 'choice_label'=>'libelle_filiere'))->getForm();
if ($form->isValid()) {
// ... maybe do some form processing, like saving the Task and Tag objects
}
return $this->render('inscriptionBundle:Default:authentification.html.twig', array(
'modif' => $form->createView(),
));
How can I do it?
I'm almost sure you want a ChoiceType/EntityType field with multiple and expanded options as true.
It should be something like this:
$form->add('filierechoisit', EntityType::class, array(
# query choices from this entity
'class' => 'inscriptionBundle\Entity\filieres',
# use the filieres.libelle_filiere property as the visible option string
'choice_label' => 'libelle_filiere',
# used to render a select box, check boxes or radios
'multiple' => true,
'expanded' => true,
));
You are mixing the form processing and form rendering. If you want user to choose which way he enters data - you do not want to process this data in two different ways until these are two independent fields.
You should just have one
->add('filierechoisit',EntityType::class,array('class'=>'inscriptionBundle\Entity\filieres', 'choice_label'=>'libelle_filiere'))
call to add field processing and left all rendering for the front-end side. You could use some JS, or API there, or in simple case, just override Twig template for that field
http://symfony.com/doc/current/cookbook/form/form_customization.html
You could render your own widget for your form here, allowing user to do some html stuff to change input.
Currently, making two add with identical names call just makes the second one override the first.

Conditionally disable validation for embedded form

I have an embedded form (for Address) which has its own validations for various properties. I embed this form in a parent form (for Person), and I have a checkbox on the parent form that says something like "Person has an address?"
When the checkbox is left unchecked, I want to disable all the validation for the embedded Address form. Or, better yet, if I can just remove the embedded form from being submitted completely that would be OK too.
I looked at using validation groups, but the use case doesn't match my own.
OK, figured this out. When adding the AddressType embedded form in my form builder, I just pass in the option for validation groups like so:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$form->add('address', new AddressType(), array(
'label' => 'Address',
'validation_groups' => function (FormInterface $form) {
if ($form->getParent()->get('toggleAddress')->getData() === false) {
return array();
}
return array('Default');
}
));
});
Within the validation group function, a check is made to see if the toggle to enable Address is off. If so, return a blank array, with removes all validation groups, including the "Default" one.
You try to fix your issue with validation group which will not cover your use case (it can but it will be tricky because en empty Address object will be linked to your Person object).
Basically, you embed your Address form everytime whereas it should only be embed when the checkbox is checked. IMHO, you should rely on dynamic form as explained here.
With this solution, you will need extra JS code in order to update you form when you click the checkbox in order to update the whole form accordingly. Then, there will be no issue about validation because the Address object will only be created when the form is embed.
Additionally (just for information), you can add/edit validation groups according to the submitted data as explained here.
Hope my answer is helpfull!

How can I add css classes to specific symfony2 form choices?

I could do this with Javascript, but I was wondering if I could add a css class to specific symfony2 form choices (not the choice field itself, but the individual choices).
For example I want to apply different css styles to individual 'option' tags inside a 'select'. I could only find a way to add a class to the tag.
Thanks in advance.
I think you can simply do:
{{ form_widget(form.name, { 'attr' : { 'class' : 'myClass' } }) }}
... as explained here, without creating your own form style.
You can override the layout of specific widgets in your form, which means you can override the way the select renders and put in custom code to check what the value of the option is and output your custom class there.
You need to apply a custom layout to your form, like so
{% form_theme form 'form_theme.html.twig' %}
Then inside the layout file you need to override the specific field for that specific form (unless of course you want to edit the choice_widget directly in which case all fields that use choice will have the functionality).
To do that you have to copy the widget, so choice_widget, then name it [_formName_fieldName_widget]
So if your form name was events and your field name was requireTickets, it'd be _events_requireTickets_widget
The answers that were already provided are very good, and I think #CriticalImpact's is the most flexible. But I just wanted to mention that if you're using a form class, you can also add extra attributes to the field via the form builder definition itself:
class SomeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('someField', "text", array("attr" => array("class" => "someCssClass")))
->add("save", "submit");
}
}
I've found this helpful for basic forms, because it still allows you to make a simple {{ form(someForm) }} call in your Twig file.
(Note that this solution still has the drawback that #CriticalImpact mentioned above)
Add attributes like CSS styles to individual choices can nowadays be achieved with choice_attr, e.g.:
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...
$builder->add('attending', ChoiceType::class, array(
'choices' => array(
'Yes' => true,
'No' => false,
'Maybe' => null,
),
'choice_attr' => function($val, $key, $index) {
// adds a class like attending_yes, attending_no, etc
return ['class' => 'attending_'.strtolower($key)];
},
));

Resources