django-suit icon indicating copy to clipboard operation
django-suit copied to clipboard

`django-select2` doesn't work on inline forms

Open antitoxic opened this issue 9 years ago • 12 comments

I'm referring to https://github.com/applegrew/django-select2/

I'm using the AutoModelSelect2Field as per example: https://github.com/darklow/django-suit-examples/blob/master/admin.py#L337

Django-select is working with standard forms but not working with inline forms. When a user presses "Add new ...." in inline forms the new inputs copies over from the 0-indexed form which doesnt exactly work because the select2 html is copied but the events are triggered not for the new fields but for the initial 0-indexed form.

Issues i found in research and consider interesting:

  • https://github.com/applegrew/django-select2/pull/127
  • https://github.com/applegrew/django-select2/issues/35
  • https://github.com/darklow/django-suit/issues/216

antitoxic avatar Jan 30 '15 13:01 antitoxic

See my comment here: https://github.com/darklow/django-suit/issues/309#issuecomment-62850832

darklow avatar Jan 30 '15 13:01 darklow

@darklow this is not the case. I know about the hook. Try it. It gets ugly.

Somehow django-select2 only triggers for the empty-form or existing/extra forms

antitoxic avatar Jan 30 '15 13:01 antitoxic

I don't currently have time to explain every line, but this is how i achieved select2 in inlines in one of my clients project. Here i am duplicating select2 that has ajax autocomplete in it.

Extend: project/templates/admin/project/module/change_form.html

{% extends 'admin/project/change_form.html' %}

{% block extrajs %}
    {{ block.super }}
    <script type="text/javascript">
        $(function () {
            Suit.after_inline.register('init_select2', function (inline_prefix, $row) {
                var i = $row.attr('id').replace(inline_prefix + '-', '');
                var id_ = 'id_' + inline_prefix + '-' + i + '-target';
                var id = '#' + id_;

                $row.find('.select2-container').remove();
                console.info(inline_prefix);

                $(id).data('field_id', $('#id_' + inline_prefix + '-0-target').data('field_id'));
                $(id).change(django_select2.onValChange).data('userGetValText', null);
                $(id).select2({
                    'allowClear': false,
                    'initSelection': django_select2.onInit,
                    'multiple': false, 'minimumInputLength': 2,
                    'minimumResultsForSearch': 6, 'closeOnSelect': false,
                    'width': '280px', 'ajax': {'dataType': 'json', 'quietMillis': 100,
                        'url': '/select2/fields/auto.json',
                        'data': django_select2.runInContextHelper(django_select2.get_url_params, id_),
                        'results': django_select2.runInContextHelper(django_select2.process_results, id_)}, 'placeholder': ''});

            });
        });

    </script>
{% endblock %}

image

darklow avatar Jan 30 '15 14:01 darklow

This looks cool. I am trying to do something like this based on the generated code from django-select2 but this seems better. I am testing it right now.

I'm guessing you ditched the hashed field names that django-select2 generated?

antitoxic avatar Jan 30 '15 14:01 antitoxic

I can't remember in details, since it was a while ago i wrote this code. But basically what i did is checked what JS code is used in single existing inline and on hook replicated it, just with the correct selectors and references. If you use other select2 field then script may vary, but the point would be the same.

darklow avatar Jan 30 '15 14:01 darklow

@darklow i just tested latest master of django-select2 (pip install -e git+https://github.com/applegrew/django-select2.git#egg=django-select2).

It has some improvements. We can now use the following in suit:

$(function () {
    Suit.after_inline.register('init_select2', function (inline_prefix, $row) {
        var i = $row.attr('id').replace(inline_prefix + '-', '');
        $row.find('[data-select2-id]').each(function() {
            var $this = $(this)
            var id = $this.attr('id');
            var key = id.replace('-'+i+'-', '_')
            window.django_select2[key](id, $this.data('select2Id'))
        })
    });
});

And it works for with any fields, with any select2 options that were configured as options for the form widgets in python.

antitoxic avatar Jan 30 '15 15:01 antitoxic

@antitoxic thanks for sharing, these are good news.

darklow avatar Jan 30 '15 19:01 darklow

Any updates on this issue? I have the same problem plus I don't see filed label. screen

banzayats avatar Apr 09 '15 07:04 banzayats

I had to change the code of @antitoxic a little to make this work with Model/HeavySelect2Widget django-suit 0.2.15 and Django-Select2 5.1.0.

$(function () {
    Suit.after_inline.register('init_select2', function (inline_prefix, $row) {
        $row.find('[data-field_id]').each(function() {

            // Remove generated elements of select2
            $(this).parent().find('span.select2').remove();

            // Reset select2 classes on select
            $(this).removeClass('select2-hidden-accessible');

            // Do the same as django_select2 would do
            // see https://github.com/applegrew/django-select2/blob/5.1.0/django_select2/static/django_select2/django_select2.js
            var field_id = $(this).data('field_id');
            $(this).select2({
                ajax: {
                    data: function (params) {
                        return {
                            term: params.term,
                            page: params.page,
                            field_id: field_id
                        };
                    },
                    processResults: function (data, page) {
                        return {
                            results: data.results
                        };
                    }
                }
            });

        })
    });
});

I also added this CSS since the spans of select2 were messed up too:

.form-horizontal .inline-related .select2 .selection,
.form-horizontal .inline-related .select2 .select2-selection {
    display: block !important;
}

.form-horizontal .inline-related .select2 .dropdown-wrapper {
    display: inline !important;
}

I've only done some quick tests with this, so there still might be some issues. Seems to work fine though.

strayer avatar Oct 02 '15 18:10 strayer

:+1:

SalahAdDin avatar Oct 05 '15 01:10 SalahAdDin

to let you know, i found this and it worked for me. I still have to deal with a few css bugs https://gist.github.com/yuchant/d935208978a1fc6e3098

msi2 avatar Sep 13 '16 14:09 msi2

It worked for me by adding the following line in the static/suit/js/suit.js

Add:

(function ($) {
    Suit.after_inline.register('init_select2', function(inline_prefix, row){
        $(row).find('select').select2(); 
    });

DjThopson avatar Nov 24 '17 18:11 DjThopson