在 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>