如何将动态 HTML 的 Razor Pages 中的多个实体添加到可编辑实体?
How to add multiple entities in Razor Pages with dynamic HTML to the editable entity?
我有一个 ASP.NET Core 3.0 Web 应用程序,其中包含生成的剃刀页面。型号如下:
public class Element
{
public int ElementID { get; set; }
public string Name { get; set; }
public string Discriminator { get; private set; }
}
public class BucketListElement : Element
{
public int BucketListID { get; set; }
public string Description { get; set; }
public bool Completed { get; set; }
public BucketList BucketList { get; set; }
public Progression Progression { get; set; }
}
public class Progression
{
public int ProgressionID { get; set; }
public int ElementID { get; set; }
public ICollection<BLETask> BLETasks { get; set; }
public BucketListElement BLElement { get; set; }
}
public class BLETask
{
public int BLETaskID { get; set; }
public int ProgressionID { get; set; }
public string Text { get; set; }
public bool Completed { get; set; }
public Progression Progression { get; set; }
}
BucketListElement 有 1 个进度。一个进程可以有 0..* BucketListElementTasks (BLETask)。创建 BucketListElement 后,我们可以导航到编辑页面,我希望能够在那里执行以下操作:
用户可以按“+”号,添加一个带有复选框的字段,或者可以按“-”号,删除旁边带有复选框的字段。每个字段都需要填写,保存后应将尽可能多的 BLETasks 分配给已编辑的 BucketListElement 的 Progression 实体(通过外键)与用户创建和填写的字段一样多。
Edit page layout after clicking the "+" sign twice (red part is needed)
如果我知道的没错,我可以动态地操作 HTML 以使用 JavaScript / Ajax 添加和删除那些字段,但不幸的是我没有这方面的经验,这个这就是为什么我请求你的帮助。
更新:
根据 @mj1313 的建议更改,添加 BLETasks 工作正常,但我希望能够编辑已经注册的 BLETasks,所以我将此代码插入到 ID 为“Tasks”的 Edit.cshtml 中。现在看起来像这样:
<div class="form-group">
<label asp-for="BucketListElement.Progression.BLETasks" class="control-label"></label>
<button id="addTask" class='btn btn-primary'>+</button>
<div id="Tasks" style="margin-top:10px">
@{
int indexCounter = 0;
int taskCounter = 1;
foreach (var task in Model.BucketListElement.Progression.BLETasks)
{
<div class="taskRow">
<label>Task @taskCounter:</label>
<input class="form-control" asp-for="@Model.BucketListElement.Progression.BLETasks[indexCounter].Text" required="required" />
<input class="largerCheckbox" asp-for="@Model.BucketListElement.Progression.BLETasks[indexCounter].Completed" />
<button class="btn btn-danger" style="padding-top:1px" onclick="deleteRow(this)" value="@indexCounter">-</button>
</div>
indexCounter++;
taskCounter++;
}
}
</div>
现在从现有的 BLETasks 中只能删除最后一行(以及由脚本(“+”按钮)创建的行)。如果我在第一个 n-1 行的末尾按下“-”按钮,就像我单击“保存”按钮一样。
如果我删除一个必填字段的文本(以便能够留在页面上)并单击第一个 n-1 行的“-”按钮之一,则会发生这种情况:
After deleting a required field and deleting one of the first n-1 row
我根据你的描述做了一个例子,你可以参考下面的代码:
Edit.cshtml:
@page
@model WebApplication9.Pages.EditModel
@{
}
<style>
.largerCheckbox {
width: 25px;
height: 25px;
margin-left: 20px;
margin-right: 20px;
vertical-align: middle
}
</style>
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="BucketListElement.Name" class="control-label"></label>
<input asp-for="BucketListElement.Name" class="form-control" />
<span asp-validation-for="BucketListElement.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BucketListElement.Description" class="control-label"></label>
<input asp-for="BucketListElement.Description" class="form-control" />
<span asp-validation-for="BucketListElement.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BucketListElement.Progression.BLETasks" class="control-label"></label>
<button id="addTask" class='btn btn-primary'>+</button>
<div id="Tasks" style="margin-top:10px">
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
@section scripts{
<script>
var count = 1;
$("#addTask").on("click", function () {
var htmlstring = "<div class='taskRow'><label>Task" + count + "</label>";
htmlstring += "<input type='text' name='BucketListElement.Progression.BLETasks[" + (count - 1) +"].Text' required='required'>";
htmlstring += "<input type='checkbox' name='BucketListElement.Progression.BLETasks[" + (count - 1) +"].Completed' class='largerCheckbox' value='true'>";
htmlstring += "<button class='btn btn-danger' style='padding-top:1px' onclick='deleteRow(this)' value='" + (count - 1)+"'>-</button></div>"
$("#Tasks").append(htmlstring);
count++;
})
function deleteRow(element) {
var currentRow = parseInt($(element).val());
let nextsiblings = document.querySelectorAll('.taskRow:nth-child(' + (currentRow + 1) + ') ~ *');
for (var i = 0; i < nextsiblings.length; i++) {
var childElements = nextsiblings[i].children;
childElements[0].textContent = "Task" + (currentRow + 1);
childElements[1].setAttribute("name", "BucketListElement.Progression.BLETasks[" + currentRow + "].Text");
childElements[2].setAttribute("name", "BucketListElement.Progression.BLETasks[" + currentRow + "].Completed");
childElements[3].setAttribute("value", currentRow)
currentRow++;
}
$(element).parent("div").remove();
count--;
}
</script>
}
Edit.cshtml.cs:
public class EditModel : PageModel
{
[BindProperty]
public BucketListElement BucketListElement { get; set; }
public void OnGet()
{
BucketListElement = new BucketListElement
{
Name = "Element1",
Description = "AAA"
};
}
public void OnPost()
{
}
}
结果:
我有一个 ASP.NET Core 3.0 Web 应用程序,其中包含生成的剃刀页面。型号如下:
public class Element
{
public int ElementID { get; set; }
public string Name { get; set; }
public string Discriminator { get; private set; }
}
public class BucketListElement : Element
{
public int BucketListID { get; set; }
public string Description { get; set; }
public bool Completed { get; set; }
public BucketList BucketList { get; set; }
public Progression Progression { get; set; }
}
public class Progression
{
public int ProgressionID { get; set; }
public int ElementID { get; set; }
public ICollection<BLETask> BLETasks { get; set; }
public BucketListElement BLElement { get; set; }
}
public class BLETask
{
public int BLETaskID { get; set; }
public int ProgressionID { get; set; }
public string Text { get; set; }
public bool Completed { get; set; }
public Progression Progression { get; set; }
}
BucketListElement 有 1 个进度。一个进程可以有 0..* BucketListElementTasks (BLETask)。创建 BucketListElement 后,我们可以导航到编辑页面,我希望能够在那里执行以下操作: 用户可以按“+”号,添加一个带有复选框的字段,或者可以按“-”号,删除旁边带有复选框的字段。每个字段都需要填写,保存后应将尽可能多的 BLETasks 分配给已编辑的 BucketListElement 的 Progression 实体(通过外键)与用户创建和填写的字段一样多。
Edit page layout after clicking the "+" sign twice (red part is needed)
如果我知道的没错,我可以动态地操作 HTML 以使用 JavaScript / Ajax 添加和删除那些字段,但不幸的是我没有这方面的经验,这个这就是为什么我请求你的帮助。
更新: 根据 @mj1313 的建议更改,添加 BLETasks 工作正常,但我希望能够编辑已经注册的 BLETasks,所以我将此代码插入到 ID 为“Tasks”的 Edit.cshtml 中。现在看起来像这样:
<div class="form-group">
<label asp-for="BucketListElement.Progression.BLETasks" class="control-label"></label>
<button id="addTask" class='btn btn-primary'>+</button>
<div id="Tasks" style="margin-top:10px">
@{
int indexCounter = 0;
int taskCounter = 1;
foreach (var task in Model.BucketListElement.Progression.BLETasks)
{
<div class="taskRow">
<label>Task @taskCounter:</label>
<input class="form-control" asp-for="@Model.BucketListElement.Progression.BLETasks[indexCounter].Text" required="required" />
<input class="largerCheckbox" asp-for="@Model.BucketListElement.Progression.BLETasks[indexCounter].Completed" />
<button class="btn btn-danger" style="padding-top:1px" onclick="deleteRow(this)" value="@indexCounter">-</button>
</div>
indexCounter++;
taskCounter++;
}
}
</div>
现在从现有的 BLETasks 中只能删除最后一行(以及由脚本(“+”按钮)创建的行)。如果我在第一个 n-1 行的末尾按下“-”按钮,就像我单击“保存”按钮一样。 如果我删除一个必填字段的文本(以便能够留在页面上)并单击第一个 n-1 行的“-”按钮之一,则会发生这种情况: After deleting a required field and deleting one of the first n-1 row
我根据你的描述做了一个例子,你可以参考下面的代码:
Edit.cshtml:
@page
@model WebApplication9.Pages.EditModel
@{
}
<style>
.largerCheckbox {
width: 25px;
height: 25px;
margin-left: 20px;
margin-right: 20px;
vertical-align: middle
}
</style>
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="BucketListElement.Name" class="control-label"></label>
<input asp-for="BucketListElement.Name" class="form-control" />
<span asp-validation-for="BucketListElement.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BucketListElement.Description" class="control-label"></label>
<input asp-for="BucketListElement.Description" class="form-control" />
<span asp-validation-for="BucketListElement.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BucketListElement.Progression.BLETasks" class="control-label"></label>
<button id="addTask" class='btn btn-primary'>+</button>
<div id="Tasks" style="margin-top:10px">
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
@section scripts{
<script>
var count = 1;
$("#addTask").on("click", function () {
var htmlstring = "<div class='taskRow'><label>Task" + count + "</label>";
htmlstring += "<input type='text' name='BucketListElement.Progression.BLETasks[" + (count - 1) +"].Text' required='required'>";
htmlstring += "<input type='checkbox' name='BucketListElement.Progression.BLETasks[" + (count - 1) +"].Completed' class='largerCheckbox' value='true'>";
htmlstring += "<button class='btn btn-danger' style='padding-top:1px' onclick='deleteRow(this)' value='" + (count - 1)+"'>-</button></div>"
$("#Tasks").append(htmlstring);
count++;
})
function deleteRow(element) {
var currentRow = parseInt($(element).val());
let nextsiblings = document.querySelectorAll('.taskRow:nth-child(' + (currentRow + 1) + ') ~ *');
for (var i = 0; i < nextsiblings.length; i++) {
var childElements = nextsiblings[i].children;
childElements[0].textContent = "Task" + (currentRow + 1);
childElements[1].setAttribute("name", "BucketListElement.Progression.BLETasks[" + currentRow + "].Text");
childElements[2].setAttribute("name", "BucketListElement.Progression.BLETasks[" + currentRow + "].Completed");
childElements[3].setAttribute("value", currentRow)
currentRow++;
}
$(element).parent("div").remove();
count--;
}
</script>
}
Edit.cshtml.cs:
public class EditModel : PageModel
{
[BindProperty]
public BucketListElement BucketListElement { get; set; }
public void OnGet()
{
BucketListElement = new BucketListElement
{
Name = "Element1",
Description = "AAA"
};
}
public void OnPost()
{
}
}
结果: