Is there way to call a Javascript function when a Django Admin Popup (Add, Update, Delete) completes?

Viewed 234

Image

I have this situation, where I have bind the change event on Person field.

We rely on some JavaScript to be run each time a select value changes. It is currently listening to the change event of said element, which works fine when the user clicks a value directly in the menu proposed by the select.

Sadly, when this select is populated through the Admin Popup functionality, it seems the change event is not fired for the select, as our callback is not executed, even though the element's value is actually changed.

Is there another event we can listen to to get the same behaviour than when the user clicks a value directly from the list ?

2 Answers

As you can see in django source code, change event is not fired when updating a related object. While it is fired on deleting and adding.

I first thought it was a bug, but actually it makes sense, as the value is not necessarily/actually updated.

However, if you need such event to be triggered in your use case, this is indeed a problem. The best I can suggest is to override this behavior in your own JS (make sure to call it after Django's JS is loaded of course):

window.djangoDismissChangeRelatedObjectPopup = window.dismissChangeRelatedObjectPopup;

window.dismissChangeRelatedObjectPopup = function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
    const id = win.name.replace(/^edit_/, '');
    const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
    const selects = $(selectsSelector);
    window.djangoDismissChangeRelatedObjectPopup(win, objId, newRepr, newId);
    selects.trigger('change');
}

Thus, the change event should be fired whenever a related object is updated.

Incase anyone want the full solution for add ,update and delete:

window.djangoDismissChangeRelatedObjectPopup = window.dismissChangeRelatedObjectPopup;

window.dismissChangeRelatedObjectPopup = function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
    const id = win.name.replace(/^edit_/, '');
    const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
    const selects = $(selectsSelector);
    window.djangoDismissChangeRelatedObjectPopup(win, objId, newRepr, newId);
    selects.trigger('change');
};

window.ORIGINAL_dismissAddRelatedObjectPopup = window.dismissAddRelatedObjectPopup;
window.dismissAddRelatedObjectPopup = function(win, newId, newRepr) {
    ORIGINAL_dismissAddRelatedObjectPopup(win, newId, newRepr);
    const name = win.name;
    const elem = document.getElementById(name);
    $(elem).trigger('change');
};

window.ORIGINAL_dismissDeleteRelatedObjectPopup = window.dismissDeleteRelatedObjectPopup;
window.dismissDeleteRelatedObjectPopup = function(win, objId) {
    ORIGINAL_dismissDeleteRelatedObjectPopup(win, objId);
    const id = win.name.replace(/^delete_/, '');
    const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
    const selects = $(selectsSelector);
    selects.trigger('change');
}
Related