1. ======================================
    
  2. JavaScript customizations in the admin
    
  3. ======================================
    
  4. 
    
  5. .. _admin-javascript-inline-form-events:
    
  6. 
    
  7. Inline form events
    
  8. ==================
    
  9. 
    
  10. You may want to execute some JavaScript when an inline form is added or removed
    
  11. in the admin change form. The ``formset:added`` and ``formset:removed`` events
    
  12. allow this. ``event.detail.formsetName`` is the formset the row belongs to.
    
  13. For the ``formset:added`` event, ``event.target`` is the newly added row.
    
  14. 
    
  15. .. versionchanged:: 4.1
    
  16. 
    
  17.     In older versions, the event was a ``jQuery`` event with ``$row`` and
    
  18.     ``formsetName`` parameters. It is now a JavaScript ``CustomEvent`` with
    
  19.     parameters set in ``event.detail``.
    
  20. 
    
  21. In your custom ``change_form.html`` template, extend the
    
  22. ``admin_change_form_document_ready`` block and add the event listener code:
    
  23. 
    
  24. .. code-block:: html+django
    
  25. 
    
  26.     {% extends 'admin/change_form.html' %}
    
  27.     {% load static %}
    
  28. 
    
  29.     {% block admin_change_form_document_ready %}
    
  30.     {{ block.super }}
    
  31.     <script src="{% static 'app/formset_handlers.js' %}"></script>
    
  32.     {% endblock %}
    
  33. 
    
  34. .. code-block:: javascript
    
  35.     :caption: ``app/static/app/formset_handlers.js``
    
  36. 
    
  37.     document.addEventListener('formset:added', (event) => {
    
  38.         if (event.detail.formsetName == 'author_set') {
    
  39.             // Do something
    
  40.         }
    
  41.     });
    
  42.     document.addEventListener('formset:removed', (event) => {
    
  43.         // Row removed
    
  44.     });
    
  45. 
    
  46. Two points to keep in mind:
    
  47. 
    
  48. * The JavaScript code must go in a template block if you are inheriting
    
  49.   ``admin/change_form.html`` or it won't be rendered in the final HTML.
    
  50. * ``{{ block.super }}`` is added because Django's
    
  51.   ``admin_change_form_document_ready`` block contains JavaScript code to handle
    
  52.   various operations in the change form and we need that to be rendered too.
    
  53. 
    
  54. Supporting versions of Django older than 4.1
    
  55. --------------------------------------------
    
  56. 
    
  57. If your event listener still has to support older versions of Django you have
    
  58. to use jQuery to register your event listener. jQuery handles JavaScript events
    
  59. but the reverse isn't true.
    
  60. 
    
  61. You could check for the presence of ``event.detail.formsetName`` and fall back
    
  62. to the old listener signature as follows:
    
  63. 
    
  64. .. code-block:: javascript
    
  65. 
    
  66.     function handleFormsetAdded(row, formsetName) {
    
  67.         // Do something
    
  68.     }
    
  69. 
    
  70.     $(document).on('formset:added', (event, $row, formsetName) => {
    
  71.         if (event.detail && event.detail.formsetName) {
    
  72.             // Django >= 4.1
    
  73.             handleFormsetAdded(event.target, event.detail.formsetName)
    
  74.         } else {
    
  75.             // Django < 4.1, use $row and formsetName
    
  76.             handleFormsetAdded($row.get(0), formsetName)
    
  77.         }
    
  78.     })