1

我有一个部分视图,如下所示:

@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?因为添加多行会添加多个projectid 输入框。

更新

@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 调用,但第二个调用不会很重,因为它要求特定元素。

4

0 回答 0