MVC 5 - 从部分视图注册使用BeginCollectionItem的JavaScript事件

时间:2017-03-16 10:22:19

标签: javascript jquery asp.net-mvc asp.net-mvc-5 begincollectionitem

我的部分视图如下:

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

0 个答案:

没有答案