Search code examples
javascriptdjangoautocompletejquery-select2admin

Django admin - autocomplete select doesn't emit "change" event


I have a model, Color, with a foreign key mill that I'd like to autocomplete. Furthermore, I'd like to detect when the mill select box changes and do something with that in Javascript. However, I can't seem to trigger any JS off the select box being changed.

I set up my admin like so:

# admin.py

class MillAdmin(admin.ModelAdmin):
    search_fields = ['name']

class ColorAdmin(admin.ModelAdmin):
    class Media:
        js = ['js/jquery/jquery.min.js', 'js/admin/some-function.js',]

    autocomplete_fields = ['mill']

And I write some Javascript:

// some-function.js

console.log('loaded script');
document.addEventListener('change', (function(e) {
    console.log('detected change event somewhere')
}))
console.log('event listener added')

In my browser console, when I visit the Color page, I see:

loaded script
event listener added

But when I select a mill, nothing more is logged.

Further notes:
The autocomplete itself is working just fine -- I am able to choose the mill I want, save, etc. Furthermore, if I remove autocomplete_fields = ['mill'] from my admin, I see that the vanilla select box does trigger the change event as expected:

loaded script
event listener added
detected change event somewhere

I dug around in the source code long enough to find that Django is using Select2, which promises to emit the change event just as if it were a normal select box. But if that is happening, something else in the page must be eating it, because I'm not seeing it. What's going on? If there's a conflict between Django and Select2, does anyone know a workaround? Thanks!


Solution

  • Events triggered by jQuery cannot be observed by native event listeners. Select2 uses jQuery's trigger function to handle events, which doesn't fire native DOM events, but you can swap the jQuery trigger for a native DOM one as illustrated here https://github.com/select2/select2/issues/4686