SonataAdminBundle: Required sonata_type_model_autocomplete causing "An invalid form control with name='' is not focusable"
Environment
Sonata packages
$ composer show sonata-project/*
sonata-project/admin-bundle 3.4.0 The missing Symfony Admin G...
sonata-project/block-bundle 3.1.1 Symfony SonataBlockBundle
sonata-project/cache 1.0.7 Cache library
sonata-project/classification-bundle 3.1.0 Symfony SonataClassificatio...
sonata-project/core-bundle 3.0.3 Symfony SonataCoreBundle
sonata-project/datagrid-bundle 2.2 Symfony SonataDatagridBundle
sonata-project/doctrine-extensions 1.0.2 Doctrine2 behavioral extens...
sonata-project/doctrine-orm-admin-bundle 3.0.5 Symfony Sonata / Integrate ...
sonata-project/easy-extends-bundle 2.1.10 Symfony SonataEasyExtendsBu...
sonata-project/exporter 1.5.0 Lightweight Exporter library
sonata-project/intl-bundle 2.2.4 Symfony SonataIntlBundle
sonata-project/media-bundle 3.1.0 Symfony SonataMediaBundle
sonata-project/notification-bundle 3.0.0 Symfony SonataNotificationB...
Symfony packages
$ composer show symfony/*
symfony/assetic-bundle v2.8.0 Integrates Assetic into Symfony2
symfony/monolog-bundle 2.11.1 Symfony MonologBundle
symfony/polyfill-apcu v1.2.0 Symfony polyfill backporting apcu_* func...
symfony/polyfill-intl-icu v1.2.0 Symfony polyfill for intl's ICU-related ...
symfony/polyfill-mbstring v1.2.0 Symfony polyfill for the Mbstring extension
symfony/polyfill-php54 v1.2.0 Symfony polyfill backporting some PHP 5....
symfony/polyfill-php55 v1.2.0 Symfony polyfill backporting some PHP 5....
symfony/polyfill-php56 v1.2.0 Symfony polyfill backporting some PHP 5....
symfony/polyfill-php70 v1.2.0 Symfony polyfill backporting some PHP 7....
symfony/polyfill-util v1.2.0 Symfony utilities for portability of PHP...
symfony/security-acl v3.0.0 Symfony Security Component - ACL (Access...
symfony/swiftmailer-bundle v2.3.11 Symfony SwiftmailerBundle
symfony/symfony v2.8.8 The Symfony PHP framework
PHP version
$ php -v
PHP 7.0.9 (cli) (built: Jul 21 2016 08:19:58) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.9, Copyright (c) 1999-2016, by Zend Technologies
with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans
Subject
First of all this could be related to #1994 and #3446 but the first one was never marked as fixed and the former has a commit that should have fix it but still getting the same error message.
I have some sonata_type_model_autocomplete fields in an admin entity that fail to validate correctly in Chrome (52 right now) when trying to create a new entity from Sonata Admin. This problem only happens with fields marked as required, for example:
class BusinessAdmin extends BaseAdmin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
...
->add(
'city',
'sonata_type_model_autocomplete',
array(
'label' => 'admin.label.city',
'required' => true,
'multiple' => false,
'property' => 'name',
)
)
...
->add(
'categories',
'sonata_type_model_autocomplete',
array(
'required' => true,
'multiple' => true,
'property' => 'name',
'to_string_callback' => function($entity, $property) {
return $entity->getName().' (ID: '.$entity->getId().')';
},
'callback' => function ($admin, $property, $value) use ($parentCategory) {
// Show only child categories from "Businesses" category
$datagrid = $admin->getDatagrid();
$queryBuilder = $datagrid->getQuery();
$queryBuilder
->andWhere($queryBuilder->getRootAlias() . '.parent=:parentCategory')
->setParameter('parentCategory', $parentCategory->getId())
;
$datagrid->setValue($property, null, $value);
},
)
)
}
}
There is another not required (and multiple) sonata_type_model_autocomplete field in the same admin entity that does not arise the issue:
->add(
'users',
'sonata_type_model_autocomplete',
array(
'required' => false,
'multiple' => true,
'label' => 'admin.label.users',
'property'=>'username',
)
)
This is the generated HTML+Java Script in the form for one off the affected fields (I know it’s messy and I’m sorry but it may help debug the issue):
<div class="form-group" id="sonata-ba-field-container-s5798adf90f5a1_city">
<label class="control-label required" for="s5798adf90f5a1_city">
Ciudad
</label>
<div class="sonata-ba-field sonata-ba-field-standard-natural">
<div class="select2-container form-control" id="s2id_s5798adf90f5a1_city_autocomplete_input"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-1">Vitoria-Gasteiz</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen1" class="select2-offscreen"></label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-1" id="s2id_autogen1"></div><input type="text" id="s5798adf90f5a1_city_autocomplete_input" value="" required="required" tabindex="-1" title="" style="display: none;"><div id="s5798adf90f5a1_city_hidden_inputs_wrap"><input type="hidden" name="s5798adf90f5a1[city]" value="2715"></div><script>
(function ($) {
var autocompleteInput = $('#s5798adf90f5a1_city_autocomplete_input');
autocompleteInput.select2({placeholder: '', // allowClear needs placeholder to work properly
allowClear: false,
enable: true,
readonly: false,
minimumInputLength: 3,
multiple: false,
width: '',
dropdownAutoWidth: false,
containerCssClass: ' form-control',
dropdownCssClass: '',
ajax: {
url: '\x2Fapp_dev.php\x2Fadmin\x2Fcore\x2Fget\x2Dautocomplete\x2Ditems',
dataType: 'json',
quietMillis: 100,
cache: false,
data: function (term, page) { // page is the one-based page number tracked by Select2
return {
//search term
'q': term,
// page size
'_per_page': 10,
// page number
'_page': page,
// admin
'uniqid': 's5798adf90f5a1',
'admin_code': 'sonata.admin.business',
// subclass
'field': 'city'
// other parameters
};
},
results: function (data, page) {
// notice we return the value of more so Select2 knows if more results can be loaded
return {results: data.items, more: data.more};
}
},
formatResult: function (item) {
return '<div class="">'+item.label+'<\/div>';// format of one dropdown item
},
formatSelection: function (item) {
return item.label;// format selected item '<b>'+item.label+'</b>';
},
escapeMarkup: function (m) { return m; } // we do not want to escape markup since we are displaying html in results
});
autocompleteInput.on('change', function(e) {
// console.log('change '+JSON.stringify({val:e.val, added:e.added, removed:e.removed}));
// remove input
if (undefined !== e.removed && null !== e.removed) {
var removedItems = e.removed;
$('#s5798adf90f5a1_city_hidden_inputs_wrap input:hidden').val(''); }
// add new input
var el = null;
if (undefined !== e.added) {
var addedItems = e.added;
$('#s5798adf90f5a1_city_hidden_inputs_wrap input:hidden').val(addedItems.id); }
});
// Initialise the autocomplete
var data = [];if (undefined==data.length || 0<data.length) { // Leave placeholder if no data set
autocompleteInput.select2('data', data);
}
// remove unneeded autocomplete text input before form submit
$('#s5798adf90f5a1_city_autocomplete_input').closest('form').submit(function()
{
$('#s5798adf90f5a1_city_autocomplete_input').remove();
return true;
});
})(jQuery);
</script>
</div>
</div>
Steps to reproduce
Add a sonata_type_model_autocomplete field linked to another entity with required set to true. Open the create new entity form in Sonata Admin and don’t select a related object for that field. Click on “Create”.
Expected results
The required fields should be focused and labeled with the browsers own validate message “Please fill this out this field” (if you are using Chrome, other browser will have another text message).
Actual results
A JavaScript error with this message in the console:
[Sonata.Admin] [core|show_form_first_tab_with_errors] show first tab with errors, [object Object]
create:1 An invalid form control with name='' is not focusable.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 4
- Comments: 27 (15 by maintainers)
I think I have this issue for every
EntityType::classfield (and maybe more Type, maybe ChoiceType too). The User can’t submit the page without having any error message, since the required field hasdisplay: none.I have to put all my field as
required: falseand use validation constraint. That’s not the best.I’ll take a look if I can fix this.
I needed a quick solution:
I think I’ve narrowed it down a little bit. The autocomplete input is being rendered with select2, and it has a non visible input field (with a
style="display:none") were the actual selected value is placed, AFAIK this is how select2 works internaly. As I made my field in the formrequiredthe browser tries to validate it but as it is non visible it’s also non focusable, thus the error. If I make this input field visible (removing the style with the inspector once the page is loaded) it shows the usual “Please fill out this field” when “Create” is clicked and the error is gone, but of course the input field is shown bellow the select2 widget.Here you can see the input that gives the problem selected in blue (with the style already removed):
I ran into this problem. Same situation. A ManyToMany association, using ModelAutocompleteType, and a “required” => true in the form type options.
From what I can tell, the input that is selected from the ‘#{{ id }}_autocomplete_input_v4’ is correctly removed. There is another input that is ‘#{{ id }}_autocomplete_input’ (same but without the v4) that is required and is unfocusable. Built-in browser validation can’t focus the required form element, which prevents the form from being submitted and doesn’t provide a useful error message.
Yes sure, I’ll do a step by step debugging as soon as I have a break at work. Just so I can go straight to the point, do you know which JavaScript file and/or function is called when any of the “Create” buttons are clicked?