Model Type: New created entity does not get selected on sortable collections
BA-JBI opened this issue · 1 comments
Environment
Sonata packages
show
$ composer show --latest 'sonata-project/*'
Direct dependencies required in composer.json:
sonata-project/translation-bundle dev-symfony7 cbd1ec0 dev-symfony7 cbd1ec0 SonataTranslationBundle
sonata-project/user-bundle 5.x-dev 2d82bcb 5.x-dev 2d82bcb Symfony SonataUserBundle
Transitive dependencies not required in composer.json:
sonata-project/admin-bundle 4.31.0 4.31.0 The missing Symfony Admin Generator
sonata-project/block-bundle 5.1.0 5.1.0 Symfony SonataBlockBundle
sonata-project/doctrine-extensions 2.4.0 2.4.0 Doctrine2 behavioral extensions
sonata-project/doctrine-orm-admin-bundle 4.17.1 4.17.1 Integrate Doctrine ORM into the SonataAdminBundle
sonata-project/exporter 3.3.0 3.3.0 Lightweight Exporter library
sonata-project/form-extensions 2.4.0 2.4.0 Symfony form extensions
sonata-project/intl-bundle 3.2.0 3.2.0 Symfony SonataIntlBundle
sonata-project/media-bundle 4.13.0 4.13.0 Symfony SonataMediaBundle
sonata-project/twig-extensions 2.4.0 2.4.0 Sonata twig extensions
PHP version
show
``` $ php -v PHP 8.3.10 (cli) (built: Aug 2 2024 16:00:00) (NTS) ```
Subject
$form->add('references', ModelType::class, [
'multiple' => true,
'sortable' => true, // <-- This produces the issue
];
When adding new Entity via "New" button, entity is created correctly but new created entity does not get selected automatically.
Problem
Because of
the rendered field is just a hidden input type.The edit_many_script does not handle the returned id value correctly.
Proposed solution
jQuery('#field_container_{{ id }}').replaceWith(html);
var newElement = jQuery('#{{ id }} [value="' + data.objectId + '"]');
if (newElement.length) {
if (newElement.is("input")) {
newElement.attr('checked', 'checked');
} else {
newElement.attr('selected', 'selected');
}
} else {
var selections = jQuery('#{{ id }}').val().split(',');
selections.push(data.objectId);
jQuery('#{{ id }}').val(selections.filter((val) => val.length > 0).join(','));
}
jQuery('#field_container_{{ id }}').trigger('sonata-admin-append-form-element');
Already tested it works
Detected one further related issue while loading the new choice list by calling https://example.com/admin/core/get-form-field-element (RetrieveFormFieldElementAction).
The problem is the FormEvents::PRE_SUBMIT listener in Symfony ChoiceType
The data in the dispatched event is a array with exactly one item and this contains a comma separated list of items.
When there is more than one item selected, then the listener clears the selection, because the list is interpreted as unknown item.
In Order to resolve that i suppose the following solution:
Add the following method:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
if ($options['multiple'] && (true === ($options['sortable'] ?? false))) {
// Make sure that scalar, submitted values are converted to arrays
// which can be submitted to the checkboxes/radio buttons
$builder->addEventListener(FormEvents::PRE_SUBMIT, static function (FormEvent $event) use ($options) {
/** @var PreSubmitEvent $event */
$form = $event->getForm();
$data = $event->getData();
if (!is_array($data) || count($data) !== 1) {
return;
}
if (str_contains($data[0], ',')) {
$event->setData(explode(',', $data[0]));
}
},1);
}
}