我的部分视图如下:
@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文件嵌入来修复此问题?更难的问题是,在使用BeginCollectionItem
添加作业时,如何防止重复ID?因为添加多行会添加多个project
id输入框。
@Stephen帮助我解决了这个问题,我从局部视图中删除了<datalist>
标记并将其放在主视图中,并使用了class而不是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调用,但第二次调用不会很重,因为它要求特定的元素。