我有一个部分视图,如下所示:
@model Whatever.Models.Jobs
@using (Html.BeginCollectionItem("JobRecords"))
{
<tr id="jobRow">
@Html.HiddenFor(m => m.Id)
<th width="40%">
@Html.EditorFor(m => m.Project, new { htmlAttributes = new { @class = "form-control", id = "project", list = "projectResults" } })
<datalist id="projectResults"></datalist>
@Html.ValidationMessageFor(m => m.Project, "", new { @class = "text-danger" })
</th>
</tr>
}
这嵌入在父视图中,例如:
@if (Model.JobRecords != null)
{
foreach (var item in Model.JobRecords)
{
Html.RenderPartial("_JobEditorRow", item);
}
}
一切正常,但正如您从部分视图中看到的那样,我想使用数据列表添加一个可搜索的框,所以我在我的控制器中添加了一个方法:
[HttpGet]
public JsonResult GetProjects(string query)
{
var list = unitOfWork.ProjectRepository.Get(c => c.Name.contains(query));
var serialized = list.Select(p => new { p.ProjectCode, p.Name});
return Json(serialized, JsonRequestBehavior.AllowGet);
}
然后添加一些使用 AJAX 的 javascript 来填充这个数据列表:
$(document).ready(function () {
var delay = 1000;
var globalTimeout = null;
function contractsCall() {
console.log("called");
$("#projectResults").empty();
$.ajax({
cache: false,
type: "GET",
contentType: "application/json;charset=utf-8",
url: "/MyController/GetProjects?query=" + $("#project").val()
})
.done(function (data) {
if (data[0] !== undefined) {
for (var i = 0; i < data.length; i++) {
$("#projectResults").append(
"<option value=" + data[i]["ProjectCode"] + ">" + data[i]["Name"] + " - " + data[i]["ProjectCode"] + "</option>"
);
}
} else {
$("#projectResults").empty();
}
});
}
$("#project").keyup(function (event) {
console.log("keyup");
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function () {
globalTimeout = null;
contractsCall();
}, delay);
});
});
此 javascript 包含在父视图中,该父视图也嵌入了部分视图。但是我添加了一个工作记录并在输入框中输入了一些内容,尽管它的 id 为project
.
我的问题是,如何从父视图注册部分视图中发生的事件;或者如果我可以在部分视图中嵌入javascript文件来解决这个问题?更困难的问题是,如何在添加工作时防止 id 重复BeginCollectionItem
?因为添加多行会添加多个project
id 输入框。
更新
@Stephen 极大地帮助我解决了这个问题,我<datalist>
从部分视图中删除了标签并将其放在主视图中,并使用类而不是 id。然后我把我的 JS 改成这样:
$("body").on("keyup", ".projectField", function () {
var self = $(this);
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function () {
globalTimeout = null;
contractsCall(self.val());
}, delay);
});
这样我就可以使用我的 AJAX 调用来搜索$(this)
输入框。我遇到的另一个问题是查看单击了哪个输入框,因此我可以更新其他一些内容,为此我使用了:
document.querySelectorAll('input[list="projectResults"]').forEach(function (element) {
element.addEventListener('input', onInput);
});
哪个电话:
function onInput(e) {
var input = e.target,
val = input.value;
list = input.getAttribute('list'),
options = document.getElementById(list).childNodes;
var row = $(this).closest("tr");
var p = row.find(".projDescription");
for (var i = 0; i < options.length; i++) {
if (options[i].value === val) {
$.ajax({
cache: false,
type: "GET",
contentType: "application/json;charset=utf-8",
url: "/ContractProject/GetProjects?query=" + val;
})
.done(function (data) {
if (data[0] !== undefined) {
console.log(data[0]["WorksDescription"]);
p.text(data[0]["WorksDescription"]);
}
});
break;
}
}
}
这有点违反直觉,因为我正在进行 2 个 AJAX 调用,但第二个调用不会很重,因为它要求特定元素。