Set easyadmin_autocomplete Select Null by default. Symfony - 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.

Related

Symfony2 personnalisation every attr radio buttons

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.

Silverstripe Gridfield Extensions - TextFields are shown as Textarea

Perhaps someone can help me. I've just installed the Grid Field Extensions Module for Silverstripe (https://github.com/ajshort/silverstripe-gridfieldextensions) because I need inline editing/adding. It works, but simple TextFields are shown as textareas and not as a simple textfield.
Can someone tell me how to change that?
The module attempts to automatically work out what field would be best for your variable. It will create a DropdownField for an Enum variable, TextareaField for a Text varialbe and so on.
If you don't want to manually set the field types for each variable that you want to be editable inline you need to change your variables a little.
TextareaField is the field set for Text variables.
TextField is the field set for Varchar variables.
For any variables that you want to be a TextField instead of a TextareaField change it's type from Text to Varchar(255) (or however large a character limit you need).
Otherwise you can manually set the fields using
setDisplayFields as described in the documentation.
$grid->getConfig()->getComponentByType('GridFieldEditableColumns')->setDisplayFields(array(
'FirstField' => function($record, $column, $grid) {
return new TextField($column);
},
'SecondField' => function($record, $column, $grid) {
return new TextField($column);
},
// ... etc for each field you want to be editable
));

Skip validation if sibling (checkbox) field contains 'false'

I have a form containing a checkbox and a "value field". The value field could be anything, a text box, a compound field, a collection - anything.
The form could look like this, for example:
field_1_label enabled [x]
value [________]
field_2_label enabled [x]
value sub_field_1 [________]
sub_field_2 [________]
field_3_label enabled [x]
value [________]
When the "enabled" field contains true, everything works fine already. When the "enabled" field contains false, I would like to disable validation on the value field and it's child fields.
So when "enabled" is un-checked, I will effectively ignore the field. I will still display it in the form, but I won't store the data and I certainly don't want it validated.
Does anybody have suggestions for how I might do this? Specifically, I'm having problems getting the validation system to ignore the value field and any potential child fields.
In Symfony 2.3 you can use false in validation_groups to have no constraints applied:
https://symfony.com/doc/current/form/button_based_validation.html
So for example, on the field containing the checkbox and value field:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver
->setDefaults([
'validation_groups' => function(FormInterface $form) {
// If the form is disabled, don't use any constraints
if ($form->get('enabled_checkbox')->getData() == false) {
return false;
}
// Otherwise, use the default validation group
return 'Default';
}
]);
}
Just remove the child fields prior to validation if the parent's checkbox is set to false.
Read more in the cookbook article How to Dynamically Modify Forms Using Form Events.
Subscribe to form events FormEvents::POST_SET_DATA and remove the field in your subscriber.
The section Adding an Event Subscriber to a Fom class covers this topic.
You can aswell introduce different validation groups for your form.
Just apply another validation group ( not containing the chield fields ) if the parent's checkbox is set to false.

Symfony - entity inheritance and form

In my project I have an abstract entity, let's call it Parent, and two child entities: ChildA and ChildB that extend Parent class. I'm using doctrine and a single table strategy, has ChildA and ChildB are similiar. This part is working ok, now my problem is with the form.
I want to have a single form that can be used to create an entity of one of those classes (ChildA or ChildB), so I want to have a first field in the form to select which kind of entity the user wants to create, and show the fields for that class (has there are only one different field, I'm using javascript to show/hide the field according to the selected class)
To accomplish this I have created a form with all the fields of both ChildA and ChildB plus the field to select the type, and my idea was in controller check the type, and then create a specific form associated with ChildA or ChildB according to the selected type, and bind it with the valus received from the main form, but the problem here is how to display the errors in this form
Anyone have a good solution for this problem?
I think you make it very difficult this way.
For this problem i would create 2 forms (FormChildA, FormChildB) with the associated fields accordingly.
Because you are using javascript anyway, just render the page with a choice and get the form with ajax:
<div id="select-type">
<button value="child_a" type="button">Select ChildA</button>
<button value="child_b" type="button">Select ChildB</button>
</div>
<div id="form-container"></div>
<script>
$('#select-type button').on('click', function(event) {
event.preventDefault();
$.get('path/to/get_ajax_form', {type: $(this).val()}, function(data) {
$('#form-container').html(data);
});
});
</script>
Create a Controller method to retrieve the form:
public function getAjaxFormAction()
{
$type = $this->get('request')->query->get('type');
switch( $type ) {
case 'child_a':
$form = $this->createForm(new FormChildA, new ChildA);
break;
case 'child_b':
$form = $this->createForm(new FormChildB, new ChildB);
break;
}
return $this->render('AcmeBundle:Forms:_type_form.html.twig', array(
'form' => $form->createView(),
'type' => $type,
));
}
Add to each form a hidden field with the form type value,
this way you can validate these forms in one method (same way as you retrieve them).
This makes it easier to modify and validate each form separately!

Can I set a general form error with callback validator?

Can I set a general form error with callback validator? I do not want to set it to a specific field, but rather to a form in general errors.
Yes, you have to create what we call a class constraint, which will be applied to the data_class itself, not to a specific field: http://symfony.com/doc/2.0/book/validation.html#classes
Here is a snippet of code to set an error to your global form and not on a field.
public function isValid(ExecutionContext $context) {
if (what ever condition) {
// Do not set the property path as shown in the documentation
$context->addViolation('This name sounds totally fake!', array(), null);
}
}
When you do not define a property path on the context, the violation is added on top level of the form. all you have to do is remove these two lines given in the official documentation :
$propertyPath = $context->getPropertyPath() . '.firstName';
$context->setPropertyPath($propertyPath);
And afterwards simple display the global errors of your form.
{{ form_errors(form) }}

Resources