Использование JQuery, AJAX и Django для создания формы со связанными раскрывающимися списками и добавления / удаления функций строки формы - PullRequest
0 голосов
/ 27 мая 2020

Как следует из названия, я создаю шаблон, который использует набор форм. В форме есть раскрывающиеся меню, а параметры загружаются с ajax из таблицы базы данных. Когда пользователь выбирает вариант из первого раскрывающегося списка, второй раскрывающийся список заполняет его параметры из базы данных, используя ajax. Всего 5 связанных раскрывающихся списков.

До сих пор все работает гладко с частями django и javascript.

Я также реализовал функцию добавления / удаления формы, следуя руководству по inte rnet, и страница успешно добавляет / удаляет формы по мере необходимости.

Однако, когда добавляется новая форма функция зависимого раскрывающегося списка не работает для новой формы. Я понимаю, что это связано с тем, что код javascript, который запускает заполнение раскрывающихся меню, отслеживает изменения в элементах формы с определенными c id.

В качестве решения (плохого) я продублировал коды javascript, которые заполняют меню, и изменил идентификатор формы элементов формы, которые прослушивает код, поскольку управление формой django изменяет идентификатор после шаблон. Это не сработало, и форма показывает странное поведение. Когда добавляется новая форма, выбор из раскрывающегося меню влияет на параметры в первом меню вместо правильного (я убедился, что идентификатор настроен правильно и соответствует тому, что генерирует django.

Я действительно борюсь с этим в течение последних двух дней, чтобы реализовать форму с зависимыми раскрывающимися меню и функциями добавления / удаления, и был бы очень признателен за решение.

Я не добавлял views / models / forms.py файлы, чтобы сделать это как можно короче, или ни одного шаблона ajax для раскрывающихся меню, как я полагаю, это чисто проблема javascript и не имеет ничего общего с Django или Python. Исправьте меня, если я ошибаюсь и я могу больше информации.

Javascript код, который добавляет / удаляет строки:

<script type='text/javascript'>
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function cloneMore(selector, prefix) {
var newElement = $(selector).clone(true);
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();


newElement.find
(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function() 
{
    var name = $(this).attr('name').replace('-' + (total-1) + '-', '-' + total + '-');
    var id = 'id_' + name;
    $(this).attr({'name': name, 'id': id}).val($(this).val()).removeAttr('checked');

});
newElement.find('label').each(function() {
    var forValue = $(this).attr('for');
    if (forValue) {
      forValue = forValue.replace('-' + (total-1) + '-', '-' + total + '-');
      $(this).attr({'for': forValue});
    }
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row:not(:last)');
conditionRow.find('.btn.add-form-row')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row').addClass('remove-form-row')
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>');
return false;
}
function deleteForm(prefix, btn) {
var total = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
if (total > 1){
    btn.closest('.form-row').remove();
    var forms = $('.form-row');
    $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
    for (var i=0, formCount=forms.length; i<formCount; i++) {
        $(forms.get(i)).find(':input').each(function() {
            updateElementIndex(this, prefix, i);
        });
    }
}
return false;
}
$(document).on('click', '.add-form-row', function(e){
e.preventDefault();
cloneMore('.form-row:last', 'form');


return false;
});
$(document).on('click', '.remove-form-row', function(e){
e.preventDefault();
deleteForm('form', $(this));
return false;
});
</script>

Javascript код, заполняющий раскрывающиеся меню (i всего 5 из них для первой формы, и я продублировал еще 5 с последовательными номерами идентификаторов для теста со второй добавленной формой

    <script>
    $("#id_form-0-od").change(function () {
        var url = $("#casingForm").attr("casing-weight-url");  // get the url of the `load_cities` view
        var odId = $(this).val();  // get the selected country ID from the HTML input

        $.ajax({                       // initialize an AJAX request
            url: url,                    // set the url of the request (= localhost:8000/hr/ajax/load-cities/)
            data: {
                'od': odId       // add the country id to the GET parameters
            },
            success: function (data) {   // `data` is the return of the `load_cities` view function
                $("#id_form-0-weight").html(data);  // replace the contents of the city input with the data that came from the server
            }
        });

    });
</script>
<script>
    $("#id_form-0-weight").change(function () {
        var url = $("#casingForm").attr("pipe-yield-url");
        var weightId = $(this).val();
        var odId = $("#id_form-0-od").val();

        $.ajax({
            url: url,
            data: {
                'weight': weightId,
                'od': odId
            },
            success: function (data) {
                $("#id_form-0-pipeyield").html(data);
            }
        });

    });
</script>

Шаблон

    <form method="post" id="casingForm"
  casing-weight-url="{% url 'wellsurfer:ajax_load_casing_weight' %}"
  pipe-yield-url="{% url 'wellsurfer:ajax_load_pipe_yield' %}"
  csg-bodyid-url="{% url 'wellsurfer:ajax_load_csg_inner_diameter' %}"
  csg-connection-url="{% url 'wellsurfer:ajax_load_csg_connection' %}"
  novalidate>




{% csrf_token %}


    {{ formset.management_form }}
{% for form in formset %}
    <div class="form-row">
    {{ form.well }}
    {{ form.type_csg_lnr }}
    {{ form.od }}
    {{ form.weight }}
    {{ form.pipeyield }}
    {{ form.inner_diameter }}
    {{ form.connection }}
    {{ form.set_depth }}
    {{ form.top_depth }}

    <div class="input-group-append">
        <button class="btn btn-success add-form-row" type="button" id="button-addon2">+ 
   </button>
    </div>
    </div>
    {% endfor %}
    <button type="submit" class="btn btn-primary">Submit</button></form>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...