How do I dynamically load elements of existing HTML when I click a button?

I will try to briefly explain the logic behind it: the form for entering the recipe data appears –> once the recipe has been saved the hidden buttons appear –> I click on the Add Ingredient button –> the contents of AddIngredientRecipe.html.

When I go to click on the Load Ingredient from Inventory button, in the modal body, nothing appears. Instead, when, once the recipe has been saved, I go to add only the ingredient, by clicking the Load Ingredient from Inventory button the ingredients present in the inventory appear. Also the Save button of addIngredientRecipe.html works, so I don’t know why Load Ingredient from Inventory doesn’t work too.

P.s.: I decided not to embed addIngredientRecipe.html in addrecipe.html for code reuse reasons. Because once the recipe has been saved, I can only insert the ingredients.

Now I leave you the codes to make you understand better.

addRecipe.html

{% extends 'beerRecipe/baseHome.html' %}
{% load static %}
{% load crispy_forms_tags %}

{% block content %}
    {% spaceless %}
        {% if user.is_authenticated %}
            <div id="message-container" class="d-none">
                <div class="alert alert-dismissible" role="alert">
                    <span id="message-content"></span>
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            </div>
            <h3 style="margin-left: 12px">Recipe</h3>
            <div class="container-fluid" id="recipe-container">
                <form id="recipe-form" method="post"
                      action="{% if recipe %}
                                {% url 'add-recipe' recipe.id %}
                                {% else %}
                                {% url 'add-recipe' %}
                                {% endif %}">
                    {% csrf_token %}
                    {% crispy recipe_form %}
                </form>
                <button class="btn btn-success" type="button" id="saveRecipeButton">Save Recipe</button>
                {% if not hide_button %}
                    <a class="btn btn-secondary" href="{% url 'home' %}" style="margin-left: 5px">Back Home</a>
                    {% else %}
                    <a class="btn btn-secondary" href="{% url 'view-recipe' recipe.id %}" style="margin-left: 5px">Back</a>
                {% endif %}
            </div>
            <div class="container-fluid d-none" id="action-buttons">
                <button type="button" id="addIngredientButton" class="btn btn-primary"
                        data-url-template="{% url 'add-ingredient-recipe' 0 %}">
                    Add Ingredient
                </button>
                <button type="button" id="addStepButton" class="btn btn-primary"
                        data-url-template="{% url 'add-step-recipe' 0 %}"
                        style="margin-left: 5px">
                    Add Step
                </button>
                <button class="btn btn-success" type="button" id="updateRecipeButton" style="margin-left: 5px"
                        data-base-url="{% url 'add-recipe' %}">
                    Update Recipe
                </button>
            </div>

            <div class="container-fluid" id="ingredient-container" style="margin-top: 25px"></div>

            <div class="container-fluid" id="step-container" style="margin-top: 25px"></div>
        {% endif %}

        <script src="{% static 'formset/jquery_formset.js' %}"></script>
        <script type="text/javascript">
            let globalRecipeId = null;
            $(document).ready(function () {

                $('#saveRecipeButton').on('click', function () {
                    const form_data = new FormData();

                    form_data.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                    form_data.append('name', document.getElementById('id_name').value);
                    form_data.append('litre', document.getElementById('id_litre').value);
                    form_data.append('ebc', document.getElementById('id_ebc').value);
                    form_data.append('ibu', document.getElementById('id_ibu').value);

                    $.ajax({
                        type: 'POST',
                        url: event.target.action,
                        data: form_data,
                        success: function (response) {
                            if (response.recipe_id) {
                                $('#saveRecipeButton').hide();
                                $('#action-buttons').removeClass('d-none');
                                globalRecipeId = response.recipe_id;
                            }
                            $('#message-content').text('Recipe added successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                            console.log(response)
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error);
                        },
                        contentType: false,
                        processData: false,
                    });
                    event.preventDefault();
                });

                $('#updateRecipeButton').on('click', function () {
                    const form_data = new FormData(document.getElementById('recipe-form'));
                    form_data.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                    const baseUrl = $(this).data('base-url');
                    const url = baseUrl + (globalRecipeId ? globalRecipeId + '/' : '');

                    $.ajax({
                        type: 'POST',
                        url: url,
                        data: form_data,
                        success: function (response) {
                            $('#message-content').text('Recipe update successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                            console.log(response)
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error);
                        },
                        contentType: false,
                        processData: false,
                    });
                    event.preventDefault();
                });

                $('#addIngredientButton').on('click', function () {

                    if (globalRecipeId) {
                        let url = $(this).data('url-template').replace('0', globalRecipeId);
                        $('#addIngredientButton').hide();
                        $('#ingredient-container').load(url);
                    }
                });

                $('#addStepButton').on('click', function () {

                    if (globalRecipeId) {
                        let url = $(this).data('url-template').replace('0', globalRecipeId);
                        $('#addStepButton').hide();
                        $('#step-container').load(url);
                    }
                });
            });
        </script>
    {% endspaceless %}
{% endblock %}

addIngredientRecipe.html

{% extends 'beerRecipe/baseHome.html' %}
{% load crispy_forms_tags %}
{% load static %}

{% block content %}
    {% spaceless %}
        {% if user.is_authenticated %}
            <div id="message-container" class="d-none">
                <div class="alert alert-dismissible" role="alert">
                    <span id="message-content"></span>
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            </div>

            <div class="container-fluid">
                <form method="post" id="ingredient-form"
                      action="{% if ingredient %}
                            {% url 'add-ingredient-recipe' recipe.id ingredient.id_ingredient.id %}
                            {% else %}
                            {% url 'add-ingredient-recipe' recipe.id %}
                            {% endif %}">
                    <h3>Recipe Ingredients</h3>
                    {% csrf_token %}
                    {% crispy ingredient_form %}
                    <h5>Property</h5>
                    <table class="table table-striped">
                        {{ property_ingredient_recipe.management_form }}
                        {% for form in property_ingredient_recipe.forms %}
                            {% if forloop.first %}
                                <thead>
                                <tr>
                                    {% for field in form.visible_fields %}
                                        <th>{{ field.label|capfirst }}</th>
                                    {% endfor %}
                                </tr>
                                </thead>
                            {% endif %}
                            <tr class="{% cycle 'row1' 'row2' %} formset_row">
                                {% for field in form.visible_fields %}
                                    <td>
                                        {% if forloop.first %}
                                            {% for hidden in form.hidden_fields %}
                                                {{ hidden }}
                                            {% endfor %}
                                        {% endif %}
                                        {{ field.errors.as_ul }}
                                        {{ field }}
                                    </td>
                                {% endfor %}
                            </tr>
                        {% endfor %}

                    </table>
                    <div role="group" style="margin-bottom: 10px">
                        <button class="btn btn-success" type="submit" id="saveIngredientButton"
                                style="margin-bottom: 15px">Save Ingredient
                        </button>
                        <input type="hidden" id="ingredient_selected" name="ingredient_selected" value="">
                        <button type="button" class="btn btn-primary" data-bs-toggle="modal"
                                data-bs-target="#ingredientModal" style="margin-bottom: 15px; margin-left: 10px"
                                data-url="{% url 'load-ingredient' %}">
                            Load ingredient from {{ default_inventory.name }}
                        </button>
                        {% if not hide_button %}
                            <a class="btn btn-secondary" type="button" href="{% url 'view-recipe' recipe.id %}" style="margin-bottom: 15px; margin-left: 10px">Back</a>
                        {% endif %}
                    </div>
                </form>

                <!-- Modal for load ingredient from default inventory-->
                <div class="modal fade" id="ingredientModal" tabindex="-1" aria-labelledby="ingredientModalLabel"
                     aria-hidden="true" role="dialog">
                    <div class="modal-dialog" role="document">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title" id="ingredientModalLabel">Ingredient
                                    of {{ default_inventory.name }}</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal"
                                        aria-label="Close"></button>
                            </div>
                            <div class="modal-body">
                                <div id="availableIngredients"></div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                                <button type="button" class="btn btn-primary" id="addSelectedIngredients">
                                    Add Selected Ingredients
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        {% endif %}

        <script src="{% static 'formset/jquery_formset.js' %}"></script>
        <script type="text/javascript">
            $('.formset_row').formset({
                prefix: 'property',
                addText: 'Add',
                deleteText: 'Delete',
                formCssClass: 'dynamic-formset1',
                addCssClass: 'add-row btn btn-primary',
                deleteCssClass: 'delete-row btn btn-danger',
                added: function (row) {
                    row.find('input[name*="name"]').removeAttr('disabled')
                }
            });

            $('#div_id_name_category').hide();
            $('#div_id_name_new_category').hide();
            const loadIngredientUrl = "{% url 'load-ingredient' %}";
            const addSelectedIngredientUrl = "{% url 'add-selected-ingredients' %}";

            $(document).ready(function () {
                let name_category = $('#id_category_choices_0');
                let name_new_category = $('#id_category_choices_1');
                let toggle_category = function () {
                    $('#div_id_name_category').toggle();
                };
                let toggle_new_category = function () {
                    $('#div_id_name_new_category').toggle();
                };
                name_category.click(function () {
                    if (name_new_category.is(":checked")) {
                        toggle_new_category();
                        name_new_category.prop('checked', false);
                    }
                    toggle_category();
                });
                name_new_category.click(function () {
                    if (name_category.is(":checked")) {
                        toggle_category();
                        name_category.prop('checked', false);
                    }
                    toggle_new_category();
                });
                $('.popover-dismiss').popover({
                    trigger: 'focus'
                });

                $('#saveIngredientButton').on('click', function () {
                    const form_data = new FormData();
                    const ingredientId = $('#ingredient_selected').val() || '';
                    form_data.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                    form_data.append('name_ingredient', document.getElementById('id_name_ingredient').value);
                    form_data.append('name_category', document.getElementById('id_name_category').value);
                    form_data.append('name_new_category', document.getElementById('id_name_new_category').value);
                    form_data.append('quantity', document.getElementById('id_quantity').value);
                    form_data.append('measurement_unit', document.getElementById('id_measurement_unit').value);
                    form_data.append('comment', document.getElementById('id_comment').value);
                    form_data.append('ingredient_selected', ingredientId);

                    if (document.getElementById('id_name_category').value && document.getElementById('id_name_new_category').value) {
                        alert("Both 'Name Category' and 'New Category Name' cannot be filled at the same time.");
                    }
                    document.querySelectorAll('.formset_row').forEach((element, index) => {
                        if (element.style.display !== 'none') {
                            let propertyName = element.querySelector('input[name$="-name"]').value;
                            let propertyValue = element.querySelector('input[name$="-value"]').value;

                            if (propertyName && propertyValue) {
                                form_data.append(`property-${index}-name`, propertyName);
                                form_data.append(`property-${index}-value`, propertyValue);
                            }
                        }
                    });
                    const formIngredientActionUrl = $('#ingredient-form').attr('action');
                    $.ajax({
                        type: 'POST',
                        url: formIngredientActionUrl,
                        data: form_data,
                        success: function (response) {
                            clearFormFields();
                            $('#message-content').text('Ingredient added successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                            console.log(response)
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error);
                        },
                        contentType: false,
                        processData: false,
                    });
                    event.preventDefault();
                });

                $('#ingredientModal').on('show.bs.modal', function () {
                    $.ajax({
                        url: loadIngredientUrl,
                        type: 'GET',
                        success: function (response) {
                            $('#availableIngredients').empty();
                            response.forEach(function (ingredient) {
                                $('#availableIngredients').append(
                                    `<input type="radio" name="ingredient" value="${ingredient.id}"> ${ingredient.name}<br>`
                                );
                            });
                            console.log(response)
                        },
                        error: function (error) {
                            console.log(error);
                        }
                    });
                });

                $('#addSelectedIngredients').on('click', function () {
                    const selectedIngredientId = $('#availableIngredients input[name="ingredient"]:checked').val();
                    $('#ingredient_selected').val(selectedIngredientId);

                    if (!selectedIngredientId) {
                        alert('Please select an ingredient before adding.')
                        return;
                    }

                    $.ajax({
                        url: addSelectedIngredientUrl,
                        type: 'GET',
                        data: {
                            'ingredient_id': selectedIngredientId,
                        },
                        success: function (data) {
                            $('#id_name_ingredient').val(data.name_ingredient);
                            $('#id_name_category').val(data.name_category);
                            $('#id_quantity').val(data.quantity);
                            $('#id_measurement_unit').val(data.measurement_unit);
                            updateFormset(data);
                            $('#ingredientModal').modal('hide');
                            $('#message-content').text('Ingredient added successfully');
                            $('#message-container').removeClass('d-none alert-danger').addClass('alert-success show');
                        },
                        error: function (error) {
                            $('#message-content').text('An error occurred. Please try again.');
                            $('#message-container').removeClass('d-none alert-success').addClass('alert-danger show');
                            console.log(error)
                        }
                    });
                });
            });

            function updateFormset(data) {
                let totalForms = $('#id_property-TOTAL_FORMS');
                let maxForms = parseInt(totalForms.val());
                let dataLength = data.properties.length;

                if (dataLength < maxForms) {
                    for (let i = dataLength; i < maxForms; i++) {
                        $(`#id_property-${i}-name`).closest('tr').remove();
                    }
                }
                totalForms.val(dataLength);

                data.properties.forEach((property, index) => {
                    let nameField = $(`#id_property-${index}-name`);
                    let valueField = $(`#id_property-${index}-value`);

                    if (nameField.length && valueField.length) {
                        nameField.val(property.name).prop('disabled', false);
                        valueField.val(property.value);
                    } else {
                        addForm(property,index);
                    }
                });
            }

            function addForm(property, index) {
                let rowClass = (index % 2 == 0) ? 'row1' : 'row2';
                let newRow = $(` <tr class="${rowClass} formset_row dynamic-formset1">
                                    <td>
                                        <input type="text" name="property-${index}-name" value="${property.name}" class="form-control form-control-sm">
                                    </td>
                                    <td>
                                        <input type="number" name="property-${index}-value" value="${property.value}" class="form-control form-control-sm" step="any">
                                    </td>
                                    <td>
                                        <input type="hidden" name="property-${index}-DELETE">
                                        <a class="delete-row btn btn-danger" href="javascript:void(0)">Delete</a>
                                    </td>
                                </tr>`
                );
                $('.dynamic-formset1').closest('table').find('tbody').find('.dynamic-formset1-add').before(newRow);
            }

            function clearFormFields() {
              $('#ingredient-form input[type="text"], #ingredient-form input[type="number"]').val('');
              $('#ingredient-form select').prop('selectIndex', 0);
              document.querySelectorAll('.formset_row').forEach((element) => {
                  element.querySelectorAll('input[type="number"]').forEach((input) => {
                      input.value = '';
                  });
              });
            }
        </script>
    {% endspaceless %}
{% endblock %}

views.py

@login_required
def load_ingredients_from_inventory(request):
    inventory = Inventory.objects.filter(id_user=request.user)
    default_inventory = inventory.filter(is_default=True).first()

    if default_inventory:
        inventory_ingredients = InventoryIngredient.objects.filter(id_inventory=default_inventory).select_related(
            'id_ingredient')
        ingredients = [{
            'id': inv_ingredient.id_ingredient.id,
            'name': inv_ingredient.id_ingredient.name,
            'quantity': inv_ingredient.quantity,
            'measurement_unit': inv_ingredient.measurement_unit
        } for inv_ingredient in inventory_ingredients]
    else:
        ingredients = []
    return JsonResponse(list(ingredients), safe=False)

My views.py method is correct, because when I go to add an ingredient from an already created recipe (so I go to directly load addIngredientRecipe.html) it loads the ingredients correctly. What I can’t figure out is why the script to load ingredients from inventory doesn’t work when I load addIngredientRecipe.html into addRecipe.html.

I would like to know how to solve this problem, and also if maybe I messed up the implementation to load addIngredientRecipe.html into addRecipe.html.