如何使克隆的 select2 字段工作?

问题描述 投票:0回答:1

我有两个 select2 字段作为表单内的动态搜索引擎。我需要克隆此表单,以便用户可以在这两个用作搜索引擎的字段中添加多个条目和过滤。

HTML:

<div id="formContainer">
        <div class="row mt-3">
            <div class="col col-md-4">
                <div class="form-group">
                    <label>{% trans "Aircraft" %}</label>
                    <select class="form-control" name="aircraft" id="aircraft">
                        <option value="" selected="" disabled="">{% trans "Select Aircraft" %}</option>
                        {% for aircraft in aircrafts %}
                            <option value="{{aircraft.id}}" {% if aircraft.id == log_entry.aircraft.id %}selected{% endif %}>{{aircraft.registration}}</option>
                        {% endfor %}
                    </select>
                </div>
            </div>
            <div class="col col-md-4">
                <div class="form-group">
                    <label>{% trans "Departure Aerodrome" %}</label>
                    <select class="form-control adep" name="adep" id="adep">
                        {% if not base_airport %}
                            <option disable="">{% trans "Choose one Airport" %}</option>
                        {% else %}
                            <option value="{{base_airport.icao_code}}">{{base_airport.icao_code}} - {{base_airport.name}} </option>
                        {% endif %}
                    </select>
                </div>
            </div>
            <div class="col col-md-4">
                <div class="form-group">
                    <label>{% trans "Arrival Aerodrome" %}</label>
                    <select class="form-control ades" name="ades" id="ades">
                        {% if not base_airport %}
                            <option disable="">{% trans "Choose one Airport" %}</option>
                        {% else %}
                            <option value="{{base_airport.icao_code}}">{{base_airport.icao_code}} - {{base_airport.name}} </option>
                        {% endif %}
                    </select>
                </div>
            </div>
        </div>
        <div>
            </div>
        </div>
    </div>
<div id="newForm"></div>
<div class="row mt-3">
    <div class="col">
        <button class="btn btn-primary" id="addFlightBtn">{% trans "Add New Flight" %}</button>
    </div>
</div>

我的表单在 forloop 中,因此可以有 1 个项目和许多其他项目。所以我用这个函数初始化选择字段:

$(document).ready(function () {
searchAirports(".adep", "adep-");
  searchAirports(".ades", "ades-");
});

function searchAirports(className, idName) {
  $(className).each(function (index) {
    var id = idName + index;
    $(this).attr("id", id);
    $("#" + id).select2({
      ajax: {
        url: "/flight/search_airports",
        dataType: "json",
        data: function (params) {
          return {
            search_value: params.term, // search term
          };
        },
        processResults: function (data) {
          return {
            results: $.map(data, function (obj) {
              return {
                text: obj.code + " " + obj.name,
                id: obj.code,
              };
            }),
          };
        },
        cache: true,
      },
      minimumInputLength: 3,
      placeholder: gettext("Search for a airport"),
      theme: "classic",
      tags: true,
      templateSelection: function (obj) {
        return obj.id;
      },
      allowClear: true,
    });
  });
}

一切正常。但是,如果我单击“添加新航班”按钮,则会触发一个函数,基本上它将表单克隆到一个新表单中。功能是这个:

addFlightBtn.addEventListener("click", (e) => {
e.preventDefault();
// creiamo un nuovo form
const newForm = createFlightForm();
// inseriamo il nuovo form nel div "newForm"
const newFormContainer = document.querySelector("#newForm");
newFormContainer.appendChild(newForm);


});

  // funzione per creare un nuovo form
  function createFlightForm() {
    const formContainer = document.querySelector("#formContainer");
    // cloniamo il contenuto del div "formContainer"
    const newForm = formContainer.cloneNode(true);

// creiamo un bottone "Remove"
const removeBtn = document.createElement("button");
removeBtn.classList.add("btn", "btn-danger", "mt-3");
removeBtn.textContent = "Remove";
removeBtn.addEventListener("click", () => {
  // rimuoviamo il form corrispondente quando viene cliccato il bottone "Remove"
  newForm.remove();
});

// inseriamo il bottone "Remove" nel form appena creato
newForm.appendChild(removeBtn);

return newForm;

} 目前我所知道的是,我应该使用 destroy 功能来销毁 select2 元素并创建一个新元素,但基本上我到目前为止尝试的一切都没有奏效。有没有人以前遇到过同样的情况,可以帮助我吗? 事实上,让我生活艰难的是了解如何克隆新的选择元素,给它们另一个唯一的 id 并让它们工作。

javascript django jquery-select2
1个回答
1
投票

需要注意的一些问题:

  • id
    属性在有效的 HTML 中应该是唯一的,因此在您要克隆的部分中应该没有
    id
    属性:它们无论如何都没有用,因为您不能使用它们来 uniquely 标识文档。您已经具有类属性,因此应该足以使用。出于同样的原因,不要为代码中的
    id
    元素动态添加
    select2
    属性。

  • 不要对稍后要克隆的元素调用

    select2
    。相反,保留一个 template 用于创建这些克隆。对于此类模板,HTML 具有
    template
    元素,您甚至可以使用它来动态创建第一个“表单容器”。

  • 您混合使用了 jQuery 和本机 DOM 方法。如果您想使用 jQuery,请充分利用它。

这里是一个演示(HTML 稍微简化以专注于更改)

$(document).ready(function () {
    createFlightForm(false); // Reuse code for adding flight form
});

function searchAirports(newForm, className, idName) {
  // newForm is now an argument to the function and is used to limit the scope of the loop:
  $(className, newForm).each(function (index) {
    // Don't set an id: id should be unique anyhow, and it is not useful here.
    $(this).select2({
      ajax: {
        url: "/flight/search_airports",
        dataType: "json",
        data: function (params) {
          return {
            search_value: params.term, // search term
          };
        },
        processResults: function (data) {
          return {
            results: $.map(data, function (obj) {
              return {
                text: obj.code + " " + obj.name,
                id: obj.code,
              };
            }),
          };
        },
        cache: true,
      },
      minimumInputLength: 3,
      placeholder: "Search for a airport",
      theme: "classic",
      tags: true,
      templateSelection: function (obj) {
        return obj.id;
      },
      allowClear: true,
    });
  });
}

$("#addFlightBtn").click((e) => {
    e.preventDefault();
    createFlightForm(true);
});

// funzione per creare un nuovo form
function createFlightForm(needsRemoveButton) {
    const formContainer = $("template").html(); // To clone, we just grab the HTML
    // cloniamo il contenuto del div "formContainer"
    const newForm = $(formContainer); // ...and create a new element with it.

    if (needsRemoveButton) { // <--- new function argument
        // creiamo un bottone "Remove"
        const removeBtn = $("<button>").addClass("btn btn-danger mt-3").text("Remove").click(() => {
            // rimuoviamo il form corrispondente quando viene cliccato il bottone "Remove"
            newForm.remove();
        });
        // inseriamo il bottone "Remove" nel form appena creato
        newForm.append(removeBtn);
    }
    
    // inseriamo il nuovo form nel div "newForm"
    $("#newForm").append(newForm);

    searchAirports(newForm, ".adep", "adep-");
    searchAirports(newForm, ".ades", "ades-");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>

<template>
    <div class="formContainer">
        <hr>
        <div class="form-group">
            <label>Departure Aerodrome</label>
            <select class="form-control adep" name="adep">
               <option value="AMS">AMS - Amsterdam</option>
               <option value="ROM">ROM - Rome</option>
            </select>
        </div>

        <div class="form-group">
            <label>Arrival Aerodrome</label>
            <select class="form-control ades" name="ades">
               <option value="AMS">AMS - Amsterdam</option>
               <option value="ROM">ROM - Rome</option>
             </select>
        </div>
    </div>
</template>

<div id="newForm">
</div>
<div class="col">
    <button class="btn btn-primary" id="addFlightBtn">Add New Flight</button>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.