【问题标题】:Append form field with model inside for loop (ASP.NET Razor Views)在 for 循环中附加带有模型的表单字段(ASP.NET Razor 视图)
【发布时间】:2022-01-24 09:39:30
【问题描述】:

这是我在 stackoverflow 上的第一个问题。呵呵。

我有一个编辑页面,我需要显示所有现有字段,我有一个添加按钮,我可以添加一个新字段。

这里是显示数据的编辑源代码(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。正在发生的事情是它正在创建一个新模型,并且在添加许多字段时验证不起作用。

非常感谢大家的帮助。谢谢!

【问题讨论】:

    标签: javascript asp.net asp.net-mvc asp.net-core razor


    【解决方案1】:

    我看到你在主视图中使用@Model.NutritionFacts.ToList()[i].PropertyName,在部分视图中使用ProductNutritionFactsDto。假设您的主视图接受一个模型,其中包含一个名为 ProductNutritionFactsDto 的嵌套 List&lt;ChildModel&gt;

    对于您的场景,您需要将计数传递给 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; }
    }
    

    此外,进一步编码的注意事项(关于将数据发布到后端):

    asp-for="@Model.NutritionFacts.ToList()[i].PropertyName"会生成name属性:name="[i].PropertyName",所以如果要在页面中发布所有ProductNutritionFactsDto模型,请确保后端参数为List&lt;ProductNutritionFactsDto&gt;

    [HttpPost]
    public IActionResult Index(List<ProductNutritionFactsDto> model)
    {
        if(ModelState.IsValid)
        {
           //....
        }
        return View(new TestViewModel() { NutritionFacts=model});
    }
    

    如果你只想在页面中单独传递任何一个ProductNutritionFactsDto模型,请务必添加名称属性(name="PropertyName")覆盖asp-for生成的名称,后端参数应为ProductNutritionFactsDto

    【讨论】:

      【解决方案2】:

      第一个表单组是 for 循环中的一个,在添加新字段之前,因此在单击提交按钮时验证正在工作。第二个表单组是点击添加按钮后的表单组。

      如何使用 asp-validation-for?我试过这个,但它不起作用。

          <span asp-validation-for="[@i].NutritionName" class="text-danger"></span>
      

      【讨论】:

      • 我试过 但还是不行。 . :(
      • 您好,asp-validation-for不适用于您的场景,建议使用服务器端验证ModelState.IsValid来判断验证。它工作正常。
      • 请问为什么它不起作用?但是,是的,我也在使用ModelState.IsValid 我只是想检查 asp-validation-for 是否也可以工作。非常感谢!!!
      • 我同意你的想法使用asp-validation-for="[@i].NutritionName"之类的东西。您的代码将在 html 中生成 data-valmsg-for="i" 而不是 data-valmsg-for="[3].NutritionName"。另外我尝试正确生成生成的html,但验证也不起作用,似乎无法验证ajax附加的html。
      • 哦,我明白了。太感谢了!!!对于这种行为,您有什么想法或方法可以让 asp-validation-for 起作用吗?
      猜你喜欢
      • 2019-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-04
      • 1970-01-01
      • 2020-03-26
      • 2015-03-18
      相关资源
      最近更新 更多