Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #297 -- Add Django admin' inline formset support #300

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

mardukbp
Copy link

As described in #249 and #297 django-select2 does not currently work with selects added dynamically in the Django admin.

The solution was implemented in #249 and all credit should go to Jurrian Tromp. I only added a small correction:

- jqRow.find('.select2-container').remove()
+ jqRow.find('.django-select2').parent().find('.select2-container').remove()

to only remove .select2-container when it is a sibling of .django-select2. Otherwise the wrong .select2-container might get deleted.

Copy link

codecov bot commented Sep 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.23%. Comparing base (f61b09c) to head (3599159).
Report is 16 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #300      +/-   ##
==========================================
+ Coverage   98.21%   98.23%   +0.02%     
==========================================
  Files           7        7              
  Lines         280      284       +4     
==========================================
+ Hits          275      279       +4     
  Misses          5        5              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Owner

@codingjoe codingjoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi there,

Thanks for the contribution. I wrote the Django integration too, so we can borrow some learnings and reduce the code a little.

Best
Joe

Comment on lines 71 to +95
$('.django-select2').djangoSelect2()

// This part fixes new inlines not having the correct select2 widgets
function handleFormsetAdded (row, formsetName) {
// Converting to the "normal jQuery"
const jqRow = $(row)

// Because select2 was already instantiated on the empty form, we need to remove it, destroy the instance,
// and re-instantiate it.
jqRow.find('.django-select2').parent().find('.select2-container').remove()
jqRow.find('.django-select2').djangoSelect2('destroy')
jqRow.find('.django-select2').djangoSelect2()
}

// See: https://docs.djangoproject.com/en/dev/ref/contrib/admin/javascript/#supporting-versions-of-django-older-than-4-1
$(document).on('formset:added', function (event, $row, formsetName) {
if (event.detail && event.detail.formsetName) {
// Django >= 4.1
handleFormsetAdded(event.target, event.detail.formsetName)
} else {
// Django < 4.1, use $row and formsetName
handleFormsetAdded($row.get(0), formsetName)
}
})
// End of fix
Copy link
Owner

@codingjoe codingjoe Sep 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$('.django-select2').djangoSelect2()
// This part fixes new inlines not having the correct select2 widgets
function handleFormsetAdded (row, formsetName) {
// Converting to the "normal jQuery"
const jqRow = $(row)
// Because select2 was already instantiated on the empty form, we need to remove it, destroy the instance,
// and re-instantiate it.
jqRow.find('.django-select2').parent().find('.select2-container').remove()
jqRow.find('.django-select2').djangoSelect2('destroy')
jqRow.find('.django-select2').djangoSelect2()
}
// See: https://docs.djangoproject.com/en/dev/ref/contrib/admin/javascript/#supporting-versions-of-django-older-than-4-1
$(document).on('formset:added', function (event, $row, formsetName) {
if (event.detail && event.detail.formsetName) {
// Django >= 4.1
handleFormsetAdded(event.target, event.detail.formsetName)
} else {
// Django < 4.1, use $row and formsetName
handleFormsetAdded($row.get(0), formsetName)
}
})
// End of fix
$('.django-select2').not('[name*=__prefix__]').djangoAdminSelect2()
document.addEventListener('formset:added', (event) => {
$(event.target).find('.django-select2').djangoSelect2()
})

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know where the method djangoAdminSelect2 is defined. Could you explain how this suggestion works?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

djangoAdminSelect2() is defined in autocomplete.js

$.fn.djangoAdminSelect2 = function() {
    $.each(this, function(i, element) {
        $(element).select2({
            ajax: {
                data: (params) => {
                    return {
                        term: params.term,
                        page: params.page,
                        app_label: element.dataset.appLabel,
                        model_name: element.dataset.modelName,
                        field_name: element.dataset.fieldName
                    };
                }
            }
        });
    });
    return this;
};

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my bad, it should have been djangoSelect2. I updated my suggestion.

@codingjoe codingjoe linked an issue Sep 18, 2024 that may be closed by this pull request
@codingjoe codingjoe changed the title Add support for selects added dynamically in the Django admin Fix #297 -- Add Django admin' inline formset support Sep 18, 2024
@sahilasopa
Copy link

@codingjoe the above code looks good to go, wondering when can it be reviewed and merged as a couple of my prod websites are affected, could wait a couple days before i create a fork myself and use that in my repos

@codingjoe
Copy link
Owner

@codingjoe the above code looks good to go, wondering when can it be reviewed and merged as a couple of my prod websites are affected, could wait a couple days before i create a fork myself and use that in my repos

I left a comment. Once it's resolved I am happy to release this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

🐛 Issues with django admin inline
3 participants