Last active
July 15, 2017 02:34
-
-
Save npotier/a7b2b34f0daae7205f86 to your computer and use it in GitHub Desktop.
Use the code below to add the "add buton" to a sonata model autocomplete form Raw
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// src/ACSEO/AdminBundle/Admin/ProductAdmin.php | |
// ... | |
protected function configureFormFields(FormMapper $formMapper) | |
{ | |
// ... | |
$formMapper | |
->add('codes', 'sonata_type_model_autocomplete', array( | |
'property' => "name", | |
'multiple' => true, | |
'template'=>'ACSEOAdminBundle:Form/Type:sonata_type_model_autocomplete_add.html.twig' | |
)) | |
// ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{# | |
file src/ACSEO/AdminBundle/Resources/views/Form/Type/sonata_type_model_autocomplete_add.html.twig | |
This file is part of the Sonata package. | |
(c) Thomas Rabaix <[email protected]> | |
For the full copyright and license information, please view the LICENSE | |
file that was distributed with this source code. | |
#} | |
{% spaceless %} | |
<input type="text" id="{{ id }}_autocomplete_input" value="" | |
{%- if read_only %} readonly="readonly"{% endif -%} | |
{%- if disabled %} disabled="disabled"{% endif -%} | |
{%- if required %} required="required"{% endif %} | |
/> | |
<div id="{{ id }}_hidden_inputs_wrap"> | |
{% if multiple -%} | |
{%- for idx, val in value if idx~'' != '_labels' -%} | |
<input type="hidden" name="{{ full_name }}[]" {%- if disabled %} disabled="disabled"{% endif %} value="{{ val }}"> | |
{%- endfor -%} | |
{% else -%} | |
<input type="hidden" name="{{ full_name }}" {%- if disabled %} disabled="disabled"{% endif %} value="{{ value[0]|default('') }}"> | |
{% endif -%} | |
</div> | |
{# This part is a copy / paste from sonata-project/doctrine-orm-admin-bundle/Resources/views/CRUD/edit_orm_many_to_one.html.twig #} | |
{% if sonata_admin.edit != 'admin' and sonata_admin.field_description.associationadmin.hasRoute('create') and sonata_admin.field_description.associationadmin.isGranted('CREATE') %} | |
<a href="{{ sonata_admin.field_description.associationadmin.generateUrl('create', sonata_admin.field_description.getOption('link_parameters', {})) }}" | |
onclick="return start_field_dialog_form_add_{{ id }}(this);" | |
class="btn btn-success btn-sm sonata-ba-action" | |
title="{{"Add" | trans }}" | |
> | |
<i class="fa fa-plus-circle"></i> | |
"{{"Add" | trans }}" | |
</a> | |
{% endif %} | |
{% include 'SonataDoctrineORMAdminBundle:CRUD:edit_modal.html.twig' %} | |
{% include 'SonataDoctrineORMAdminBundle:CRUD:edit_orm_many_association_script.html.twig' %} | |
{# end copy / paste #} | |
<script> | |
(function ($) { | |
var autocompleteInput = $('#{{ id }}_autocomplete_input'); | |
autocompleteInput.select2({ | |
{%- set allowClearPlaceholder = (not multiple and not required) ? ' ' : '' -%} | |
placeholder: '{{ placeholder ?: allowClearPlaceholder }}', // allowClear needs placeholder to work properly | |
allowClear: {{ required ? 'false' : 'true' }}, | |
enable: {{ disabled ? 'false' : 'true' }}, | |
readonly: {{ read_only ? 'true' : 'false' }}, | |
minimumInputLength: {{ minimum_input_length }}, | |
multiple: {{ multiple ? 'true' : 'false' }}, | |
width: '{{ width }}', | |
dropdownAutoWidth: {{ dropdown_auto_width ? 'true' : 'false' }}, | |
containerCssClass: '{{ container_css_class ~ ' form-control' }}', | |
dropdownCssClass: '{{ dropdown_css_class }}', | |
ajax: { | |
url: '{{ url ?: path(route.name, route.parameters|default([]))|e('js') }}', | |
dataType: 'json', | |
quietMillis: 100, | |
data: function (term, page) { // page is the one-based page number tracked by Select2 | |
{% block sonata_type_model_autocomplete_ajax_request_parameters %} | |
return { | |
//search term | |
'{{ req_param_name_search }}': term, | |
// page size | |
'{{ req_param_name_items_per_page }}': {{ items_per_page }}, | |
// page number | |
'{{ req_param_name_page_number }}': page, | |
// admin | |
{% if sonata_admin.admin is not null %} | |
'uniqid': '{{ sonata_admin.admin.uniqid }}', | |
'admin_code': '{{ sonata_admin.admin.code }}', | |
{% elseif admin_code %} | |
'admin_code': '{{ admin_code }}', | |
{% endif %} | |
{% if context == 'filter' %} | |
'field': '{{ full_name|replace({'filter[': '', '][value]': '', '__':'.'}) }}', | |
'_context': 'filter' | |
{% else %} | |
'field': '{{ name }}' | |
{% endif %} | |
// other parameters | |
{% if req_params is not empty %}, | |
{%- for key, value in req_params -%} | |
'{{- key|e('js') -}}': '{{- value|e('js') -}}' | |
{%- if not loop.last -%}, {% endif -%} | |
{%- endfor -%} | |
{% endif %} | |
}; | |
{% endblock %} | |
}, | |
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 {% block sonata_type_model_autocomplete_dropdown_item_format %}'<div class="{{ dropdown_item_css_class }}">'+item.label+'<\/div>'{% endblock %};// format of one dropdown item | |
}, | |
formatSelection: function (item) { | |
return {% block sonata_type_model_autocomplete_selection_format %}item.label{% endblock %};// 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; | |
{% if multiple %} | |
if(!$.isArray(removedItems)) { | |
removedItems = [removedItems]; | |
} | |
var length = removedItems.length; | |
for (var i = 0; i < length; i++) { | |
el = removedItems[i]; | |
$('#{{ id }}_hidden_inputs_wrap input:hidden[value="'+el.id+'"]').remove(); | |
} | |
{%- else -%} | |
$('#{{ id }}_hidden_inputs_wrap input:hidden').val(''); | |
{%- endif %} | |
} | |
// add new input | |
var el = null; | |
if (undefined !== e.added) { | |
var addedItems = e.added; | |
{% if multiple %} | |
if(!$.isArray(addedItems)) { | |
addedItems = [addedItems]; | |
} | |
var length = addedItems.length; | |
for (var i = 0; i < length; i++) { | |
el = addedItems[i]; | |
$('#{{ id }}_hidden_inputs_wrap').append('<input type="hidden" name="{{ full_name }}[]" value="'+el.id+'" />'); | |
} | |
{%- else -%} | |
$('#{{ id }}_hidden_inputs_wrap input:hidden').val(addedItems.id); | |
{%- endif %} | |
} | |
}); | |
// Initialise the autocomplete | |
var data = []; | |
{%- if value is not empty -%} | |
data = {%- if multiple -%}[ {%- endif -%} | |
{%- for idx, val in value if idx~'' != '_labels' -%} | |
{%- if not loop.first -%}, {% endif -%} | |
{id: '{{ val|e('js') }}', label:'{{ value['_labels'][idx]|e('js') }}'} | |
{%- endfor -%} | |
{%- if multiple -%} ] {%- endif -%}; | |
{% endif -%} | |
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 | |
$('#{{ id }}_autocomplete_input').closest('form').submit(function() | |
{ | |
$('#{{ id }}_autocomplete_input').remove(); | |
return true; | |
}); | |
})(jQuery); | |
</script> | |
{% endspaceless %} |
The "add" button can be replaced by "{% trans from 'SonataAdminBundle' %}link_add{% endtrans %}" to keep Sonata's translation
To preserve the feature of automatically selecting new items created by the add button (so you don't have to search for and select it manually), add the following to the bottom of the closure (line 183):
{% set create_url = sonata_admin.field_description.associationadmin.generateUrl('create', sonata_admin.field_description.getOption('link_parameters', {})) %}
$(document).ajaxSuccess(function(event, xhr, settings) {
if ('{{ create_url }}'.indexOf(settings.url) !== -1 && typeof xhr.responseJSON != 'string' && xhr.responseJSON.result == 'ok') {
var form = JSON.parse('{"' + decodeURI(settings.data).replace('+', ' ').replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
var item = {
id: xhr.responseJSON.objectId,
label: form['{{ sonata_admin.field_description.associationadmin.uniqid }}[name]']
};
{%- if multiple -%}
var data = autocompleteInput.select2('data');
data.push(item);
{%- else -%}
var data = item;
{%- endif -%}
autocompleteInput.select2('data', data).trigger($.Event('change', {
val: item.id,
added: item
}));
}
});
@lushc: Thank you for the code, this is someting I really miss in my project. But can you give a few more details? I added your code between
$('#{{ id }}_autocomplete_input').remove();
return true;
});
and
})(jQuery);
</script>
on line 184. The code is loaded, but nothing happens. How can I test what's wrong?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It returns an error:
The option "template" does not exist. Defined options are:...