在 for 循环内附加带有模型的表单字段(ASP.NET Razor 视图)
Append form field with model inside for loop (ASP.NET Razor Views)
这是我在 Whosebug 上的第一个问题。呵呵。
我有一个需要显示所有现有字段的编辑页面,还有一个可以添加新字段的添加按钮。
这是用于显示数据的编辑源代码(Edit.cshtml)
<div class="nutrition-field">
@for (int i = 0; i < Model.NutritionFacts.Count(); i++ )
{
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="@Model.NutritionFacts.ToList()[i].NutritionName">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="@Model.NutritionFacts.ToList()[i].Gram">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
}
</div>
这里是添加按钮的 javascript:
$(addNutrition).click(function() {
$.ajax({
url: "/Product/AddNutrition",
cache: false,
success: function (html) {
$('.nutrition-field').append(html)
}
});
});
当您单击按钮时,它将转到控制器,这是添加营养控制器的代码:
public IActionResult AddNutrition()
{
return PartialView("~/Views/Product/PartialViews/_AddNutrition.cshtml", new ProductNutritionFactsDto());
}
这是局部视图:
@model ProjectName.Dto.ProductNutritionFactsDto
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="NutritionName">
<span asp-validation-for="NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="Gram">
<span asp-validation-for="Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="PercentageDailyValue">
<span asp-validation-for="PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
它正在工作,但我希望它在 for 循环内,这样索引的计数将继续,并且它将有一个唯一的 ID。发生的事情是它正在创建一个新模型,并且在添加许多字段时验证不起作用。
非常感谢大家的帮助。谢谢!
我看到您在主视图中使用 @Model.NutritionFacts.ToList()[i].PropertyName
,在部分视图中使用 ProductNutritionFactsDto
。假设您的主视图接受一个模型包含嵌套的 List<ChildModel>
称为 ProductNutritionFactsDto
.
对于您的场景,您需要将计数传递给 ajax 并使用 ViewBag 存储计数并在局部视图中使用它:
主视图:
model TestViewModel
<button id="addNutrition" type="button">Add</button>
<form method="post">
<div class="nutrition-field">
@for (int i = 0; i < Model.NutritionFacts.Count(); i++)
{
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="@Model.NutritionFacts.ToList()[i].NutritionName">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="@Model.NutritionFacts.ToList()[i].Gram">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
}
</div>
<input type="submit" value="post" />
</form>
@section Scripts
{
<script>
$("#addNutrition").click(function () {
$.ajax({
url: "/Product/AddNutrition?index=" + $(".nutrients-name").length,
cache: false,
success: function (html) {
$('.nutrition-field').append(html)
}
});
});
</script>
}
控制器:
public IActionResult AddNutrition(int index)
{
ViewBag.Index = index;
return PartialView("~/Views/Product/PartialViews/_AddNutrition.cshtml", new ProductNutritionFactsDto());
}
局部视图:
获取 ViewBag.Index
并使用此索引添加名称属性。
@model ProductNutritionFactsDto
@{
var i = (int)ViewBag.Index;
}
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="NutritionName" name="[@i].NutritionName">
<span asp-validation-for="NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="Gram" name="[@i].Gram">
<span asp-validation-for="Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="PercentageDailyValue" name="[@i].PercentageDailyValue">
<span asp-validation-for="PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
测试模型:
public class TestViewModel
{
public List<ProductNutritionFactsDto> NutritionFacts { get; set; }
}
public class ProductNutritionFactsDto
{
[Required]
public string NutritionName { get; set; }
public string Gram { get; set; }
public string PercentageDailyValue { get; set; }
}
此外,进一步编码的注意事项(关于post将数据发送到后端):
asp-for="@Model.NutritionFacts.ToList()[i].PropertyName"
会生成name属性:name="[i].PropertyName"
,所以如果你想post页面中的所有ProductNutritionFactsDto
模型,请确保后端参数应该是 List<ProductNutritionFactsDto>
.
[HttpPost]
public IActionResult Index(List<ProductNutritionFactsDto> model)
{
if(ModelState.IsValid)
{
//....
}
return View(new TestViewModel() { NutritionFacts=model});
}
如果您只想在页面中单独传递任何一个 ProductNutritionFactsDto
模型,请务必添加名称属性(name="PropertyName"
)以覆盖 asp-for
生成的名称和后端参数应该是 ProductNutritionFactsDto
.
第一个表单组是 for 循环中的表单组,在添加新字段之前,因此在单击提交按钮时验证有效。第二个窗体组是点击添加按钮后的那个。
如何使用 asp-validation-for?我试过这个,但没用。
<span asp-validation-for="[@i].NutritionName" class="text-danger"></span>
这是我在 Whosebug 上的第一个问题。呵呵。
我有一个需要显示所有现有字段的编辑页面,还有一个可以添加新字段的添加按钮。
这是用于显示数据的编辑源代码(Edit.cshtml)
<div class="nutrition-field">
@for (int i = 0; i < Model.NutritionFacts.Count(); i++ )
{
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="@Model.NutritionFacts.ToList()[i].NutritionName">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="@Model.NutritionFacts.ToList()[i].Gram">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
}
</div>
这里是添加按钮的 javascript:
$(addNutrition).click(function() {
$.ajax({
url: "/Product/AddNutrition",
cache: false,
success: function (html) {
$('.nutrition-field').append(html)
}
});
});
当您单击按钮时,它将转到控制器,这是添加营养控制器的代码:
public IActionResult AddNutrition()
{
return PartialView("~/Views/Product/PartialViews/_AddNutrition.cshtml", new ProductNutritionFactsDto());
}
这是局部视图:
@model ProjectName.Dto.ProductNutritionFactsDto
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="NutritionName">
<span asp-validation-for="NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="Gram">
<span asp-validation-for="Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="PercentageDailyValue">
<span asp-validation-for="PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
它正在工作,但我希望它在 for 循环内,这样索引的计数将继续,并且它将有一个唯一的 ID。发生的事情是它正在创建一个新模型,并且在添加许多字段时验证不起作用。
非常感谢大家的帮助。谢谢!
我看到您在主视图中使用 @Model.NutritionFacts.ToList()[i].PropertyName
,在部分视图中使用 ProductNutritionFactsDto
。假设您的主视图接受一个模型包含嵌套的 List<ChildModel>
称为 ProductNutritionFactsDto
.
对于您的场景,您需要将计数传递给 ajax 并使用 ViewBag 存储计数并在局部视图中使用它:
主视图:
model TestViewModel
<button id="addNutrition" type="button">Add</button>
<form method="post">
<div class="nutrition-field">
@for (int i = 0; i < Model.NutritionFacts.Count(); i++)
{
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="@Model.NutritionFacts.ToList()[i].NutritionName">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="@Model.NutritionFacts.ToList()[i].Gram">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue">
<span asp-validation-for="@Model.NutritionFacts.ToList()[i].PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
}
</div>
<input type="submit" value="post" />
</form>
@section Scripts
{
<script>
$("#addNutrition").click(function () {
$.ajax({
url: "/Product/AddNutrition?index=" + $(".nutrients-name").length,
cache: false,
success: function (html) {
$('.nutrition-field').append(html)
}
});
});
</script>
}
控制器:
public IActionResult AddNutrition(int index)
{
ViewBag.Index = index;
return PartialView("~/Views/Product/PartialViews/_AddNutrition.cshtml", new ProductNutritionFactsDto());
}
局部视图:
获取 ViewBag.Index
并使用此索引添加名称属性。
@model ProductNutritionFactsDto
@{
var i = (int)ViewBag.Index;
}
<div class="nutrition-div form-group row">
<div class="col-lg-4">
<label>Nutrients name</label>
<input type="text" class="nutrients-name form-control" asp-for="NutritionName" name="[@i].NutritionName">
<span asp-validation-for="NutritionName" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>Per 100g</label>
<input type="text" class="gram form-control" asp-for="Gram" name="[@i].Gram">
<span asp-validation-for="Gram" class="text-danger"></span>
</div>
<div class="col-lg-4">
<label>% Daily value</label>
<div class="d-flex">
<input type="text" class="percentage-value form-control mr-5 w-50" asp-for="PercentageDailyValue" name="[@i].PercentageDailyValue">
<span asp-validation-for="PercentageDailyValue" class="text-danger"></span>
<a href="javascript:void(0)" class="delete-btn btn btn-fixed-height btn-secondary font-weight-bold font-size-sm px-8">
Delete
</a>
</div>
</div>
</div>
测试模型:
public class TestViewModel
{
public List<ProductNutritionFactsDto> NutritionFacts { get; set; }
}
public class ProductNutritionFactsDto
{
[Required]
public string NutritionName { get; set; }
public string Gram { get; set; }
public string PercentageDailyValue { get; set; }
}
此外,进一步编码的注意事项(关于post将数据发送到后端):
asp-for="@Model.NutritionFacts.ToList()[i].PropertyName"
会生成name属性:name="[i].PropertyName"
,所以如果你想post页面中的所有ProductNutritionFactsDto
模型,请确保后端参数应该是 List<ProductNutritionFactsDto>
.
[HttpPost]
public IActionResult Index(List<ProductNutritionFactsDto> model)
{
if(ModelState.IsValid)
{
//....
}
return View(new TestViewModel() { NutritionFacts=model});
}
如果您只想在页面中单独传递任何一个 ProductNutritionFactsDto
模型,请务必添加名称属性(name="PropertyName"
)以覆盖 asp-for
生成的名称和后端参数应该是 ProductNutritionFactsDto
.
第一个表单组是 for 循环中的表单组,在添加新字段之前,因此在单击提交按钮时验证有效。第二个窗体组是点击添加按钮后的那个。
如何使用 asp-validation-for?我试过这个,但没用。
<span asp-validation-for="[@i].NutritionName" class="text-danger"></span>