次のような部分ビューがあります。
@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);
}
}
それはすべて機能しますが、部分的なビューからわかるように、data-list を使用して検索可能なボックスを追加したいので、コントローラーにメソッドを追加します。
[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);
});
$(this)
このようにして、入力ボックスの AJAX 呼び出しを使用して検索できます。私が抱えていたもう1つの問題は、クリックされた入力ボックスを確認して、他のものを更新できるようにすることでした。
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 呼び出しを行っているため、少し直感的ではありませんが、特定の要素を要求しているため、2 つ目の呼び出しは重くなりません。