In Symfony 6, when I render en EntityType
(HTML select field) setting readonly
attribute, this field can actually be modified (since readonly
does not work for <select>
elements)..
If I set disabled
, then, I get an error as this field is required.
How can I avoid this field to be modified but rendered?
class ClientFileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('clientFileType', EntityType::class, ['label' => 'Tipo',
'required' => true,
'class' => TypeOfClientFile::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('T')
->orderBy('T.name', 'ASC');
}])
// (...)
}
This is twig template code, field is readonly
only when modifying, but editable on new entity:
{{ form_row(form.clientFileType, {'attr': {'readonly': (client_file.id != null) }}) }}
You cannot use disabled
and required
at the same time. If you think about it, you'll realize it doesn't make sense: with required
you are telling "this value needs to be filled in and sent", with disabled
you are saying "ignore and do not send the value for this field".
For this, you'll have to implement a slightly more sophisticated logic.
If the value field is to be disabled, then maybe you no longer need to display it as a select
. You do not need the options (the user can't choose a new one), so why query them and render them?
In this case, simply add a different field type for different situations: If the field is to be disabled
, show a different UI element, and send the appropriate data.
A crude example (you'll have to polish it so it suits your use-case, haven't actually ran it in my project, but the idea works):
class ClientFileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
if ($options['client_file']) {
$builder->add('clientFileType', HiddenType::class, [
'value' => $options['client_file'],
]);
$builder->add('clientFileTypeDisplay', TextType::class, [
'label' => 'Tipo',
'value' => $options['client_file_name'],
'disabled' => true,
]);
} else {
$builder
->add('clientFileType', EntityType::class, ['label' => 'Tipo',
'required' => true,
'class' => TypeOfClientFile::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('T')
->orderBy('T.name', 'ASC');
}]);
}
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'client_file' => 'int',
'client_file_name' => '',
]);
$resolver->addAllowedTypes('client_file', 'integer');
$resolver->addAllowedTypes('client_file_name', 'string');
}
}
Then when creating your form in your controller, you'll set the options if necessary:
$form = $this->createForm(ClientFileType::class, options: [
'client_file' => $client_file_id, // or 0 if not applicable,
'client_flie_name' => $client_file_name // the actual name, so you don't have to make a query in the form
]);
And when rendering it:
{{ form_row(form.clientFileType) }}
{% if client_file.id %}
{{ form_row(form.clientFileTypeDisplay) }}
{% endif %}