-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
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. |
There was a problem hiding this 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
$('.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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$('.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() | |
}) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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;
};
There was a problem hiding this comment.
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 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. |
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:
to only remove
.select2-container
when it is a sibling of.django-select2
. Otherwise the wrong.select2-container
might get deleted.