Dynamically Show/Hide Django Admin Inline Forms Based on Dropdown Selection

I'm trying to dynamically show and hide inline forms in the Django admin based on a dropdown selection. I have two inline forms: one for IndividualCustomer and another for CorporateCustomer. The goal is for the corresponding inline to appear when a specific customer type is selected from the dropdown.

Here’s what I’ve set up:

Models: I have defined IndividualCustomer, CorporateCustomer, and Customer models.

Admin: I've created inlines for both customer types and included them in the CustomerAdmin class.

Custom Template: I’m using a custom change_form.html to implement the JavaScript logic.

Models and Admin Code:

# models.py
from django.db import models

class Customer(models.Model):
    CUSTOMER_TYPE_CHOICES = [
        ('Individual', 'مشتری حقیقی'),
        ('Corporate', 'مشتری حقوقی'),
    ]
    customer_type = models.CharField(max_length=20, choices=CUSTOMER_TYPE_CHOICES)

class IndividualCustomer(models.Model):
    customer = models.OneToOneField(Customer, on_delete=models.CASCADE)
    # Other fields...

class CorporateCustomer(models.Model):
    customer = models.OneToOneField(Customer, on_delete=models.CASCADE)
    # Other fields...

# admin.py
from django.contrib import admin
from .models import Customer, IndividualCustomer, CorporateCustomer

class IndividualCustomerInline(admin.StackedInline):
    model = IndividualCustomer
    extra = 0

class CorporateCustomerInline(admin.StackedInline):
    model = CorporateCustomer
    extra = 0

@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
    inlines = [IndividualCustomerInline, CorporateCustomerInline]

Custom Template (change_form.html):

{% extends "admin/change_form.html" %}
{% load i18n static %}

{% block after_field_sets %}
{{ block.super }}

<style>
    .inline-group {
        margin-bottom: 20px;
    }
</style>

<script>
document.addEventListener('DOMContentLoaded', function () {
    function hideAllInlines() {
        const individualInline = document.querySelector('#individualcustomer_set-group');
        const corporateInline = document.querySelector('#corporatecustomer_set-group');

        if (individualInline) individualInline.style.display = 'none';
        if (corporateInline) corporateInline.style.display = 'none';
    }

    function toggleInlines() {
        const customerType = document.querySelector('#id_customer_type').value;
        const individualInline = document.querySelector('#individualcustomer_set-group');
        const corporateInline = document.querySelector('#corporatecustomer_set-group');

        if (customerType === 'Individual') {
            if (individualInline) individualInline.style.display = 'block';
            if (corporateInline) corporateInline.style.display = 'none';
        } else if (customerType === 'Corporate') {
            if (corporateInline) corporateInline.style.display = 'block';
            if (individualInline) individualInline.style.display = 'none';
        } else {
            hideAllInlines();
        }
    }

    hideAllInlines();
    toggleInlines();

    const customerTypeField = document.querySelector('#id_customer_type');
    if (customerTypeField) {
        customerTypeField.addEventListener('change', toggleInlines);
    }
});
</script>
{% endblock %}

Issue Despite implementing the above, both inline forms are displayed initially, and the expected behavior of hiding one form based on the dropdown selection is not occurring. Here are the specific issues I'm encountering:

Both IndividualCustomer and CorporateCustomer inline forms are shown when the page loads. The inlines do not toggle visibility when the dropdown selection changes. I receive console errors indicating that some elements are not found, such as Individual Inline not found!. What I’ve Tried Verified the IDs of the inline groups. Ensured the JavaScript is included correctly in the template. Checked for any JavaScript errors in the console.

How can I dynamically show and hide the Django admin inline forms based on a dropdown selection? What changes do I need to make to my JavaScript or template to ensure the inlines behave as expected?

Вернуться на верх