我有两个 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 并让它们工作。
需要注意的一些问题:
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>