【问题标题】:How to submit different parts of a form independently?如何独立提交表单的不同部分?
【发布时间】:2021-02-03 20:44:36
【问题描述】:

如图所示,我如何能够独立于表单的其余部分通过“添加标签”添加标签,这在某种意义上忽略了表单其余部分的验证。另外,反之亦然,如何在忽略添加标签“添加标签”的验证的情况下“创建”食谱

注意:红线仅用于 css 调试。

观点:

@model MVCApp.ViewModels.CreateRecipe

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm("Create", "Recipe", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Create Recipe</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        @*Heading - Select Multiple Tags:*@
        <div class="form-group">
            @Html.LabelFor(model => model.SelectedTagIds, htmlAttributes: new { @class = "control-label", style = "border: 1px solid red;" })
        </div>

        @*Search box - Tag*@
        <input type="text" id="search" name="search" placeholder="Search" style="margin: 10px;width: 165px;border: 1px solid red;" onkeyup="filter()">

        @*List Box - Tag*@
        <div class="form-group" style="border: 1px solid black;">

            @*List box*@
            <div class="col-xs-6 col-sm-4" id="listBoxDiv" style="border: 1px solid red;">
                @Html.ListBoxFor(model => model.SelectedTagIds, Model.TagList, new { @class = "col-xs-12", style = "height:300px; padding:5px;", @onchange = "getSelectedTags(this)" }) @*//OnSelectedIndexChanged*@
                @Html.ValidationMessageFor(model => model.SelectedTagIds, "", new { @class = "text-danger col-xs-12", style = "border: 1px solid red;" })
            </div>

            @*Your tags selected*@
            <div class="col-xs-6 col-sm-8" style="border: 1px solid red;" id="displaySelectedTags">
            </div>
        </div>

        @*EditorFor & Submit - Tag Name*@
        <div class="form-group">
            @Html.LabelFor(model => model.Tag.Name, htmlAttributes: new { @class = "control-label col-md-2", style = "border: 1px solid red;" }) @*sm*@
            <div class="col-md-3" style="border: 1px solid red; padding-right:0;">
                @Html.EditorFor(model => model.Tag.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Tag.Name, "", new { @class = "text-danger" })
            </div>

            @*Submit - Add Tag*@
            <div class="col-md-7" id="addTag" style="border: 1px solid red;">
                <input type="submit" value="Add Tag" class="btn btn-default" style="border: 1px solid red;" />
            </div>
        </div>

        @*File - Upload Image*@
        <div class="form-group">
            <label class="control-label col-md-2" for="file">Upload Image:</label>
            <div class="col-md-10">
                <input type="file" name="file" id="file" style="width:100%" />
            </div>
        </div>

        @*EditorFor - Recipe Title*@
        <div class="form-group">
            @Html.LabelFor(model => model.Recipe.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Recipe.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Recipe.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        @*EditorFor - Recipe Instructions*@
        <div class="form-group">
            @Html.LabelFor(model => model.Recipe.Instructions, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Recipe.Instructions, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Recipe.Instructions, "", new { @class = "text-danger" })
            </div>
        </div>

        @*Submit - Create Recipe*@
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

控制器 Post 方法:(正在进行中)

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(CreateRecipe model, HttpPostedFileBase file)
        {
            try
            {
                // TODO: Add insert logic here
                if (ModelState.IsValid)
                {
                    // Insert Image
                    if (file != null)
                    {

                    }

                    // Insert Recipe
                    int recipeId = RecipeProcessor.CreateRecipe(model.Recipe.Name, model.Recipe.Instructions);

                    // Insert TagRecipe Row
                    var count = 0;
                    foreach (var tagId in model.SelectedTagIds)
                    {
                        RecipeProcessor.CreateTagRecipe(tagId, recipeId);
                        count++;
                    }

                    return RedirectToAction("Index", new { successMessage = $"{model.Recipe.Name} added successfully" });
                }
            }
            catch (DataException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }

            // If not valid, return the same model - This should never run as JS will validate first
            return View(model);
        }

模型

    public class CreateRecipe
    {
        // A Recipe object
        public Recipe Recipe { get; set; }

        [Required(ErrorMessage = "At least one Tag is required.")]
        [Display(Name = "Select multiple tags:")]
        public int[] SelectedTagIds { get; set; }

        public IEnumerable<SelectListItem> TagList { get; set; }

        // A tag object
        public Tag Tag { get; set; }
    }

谢谢

【问题讨论】:

  • 你的问题太宽泛了。有太多方法可以完成您的要求。 了解单页应用程序 (SPA) 以及如何使用 ASP .NET 构建 SPA
  • 您不限于每页一张表格。只需添加另一个具有不同操作的表单即可。
  • @DonO 这是我最初的猜测,但“添加标签”部分/表单将在“创建”配方表单中?
  • 不,它会在外面,我会尝试用下面的示例给出一个简短的答案。
  • @C.AugustoProiete 鉴于 SPA 只是动态重写当前网页,而不是浏览器加载整个新页面的默认方法,我仍然不知道从哪里开始专门研究只能提交表单的一部分,而忽略其余部分的验证。

标签: c# html asp.net asp.net-mvc razor


【解决方案1】:

您可以在同一页面上有多个表单,指向不同的操作。如果您需要访问两个模型,那么页面的视图模型应该包含两个模型,就像您已经拥有它们一样。

控制器将有两个动作,一个用于添加配方,一个用于添加标签,或者它可以指向两个不同的控制器。

视图也可以有两种形式。在下面的示例中,它们会点击不同的控制器,但您也可以在同一个控制器上点击不同的操作。

@using (Html.BeginForm("Create", "Recipe", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
.....
}

@using (Html.BeginForm("Create", "Tag", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
.....
}

如果您这样做,要记住的一件事是可能会同时调用两个操作,因此您需要在代码中确定您正在执行哪个操作。

【讨论】:

  • 在我现在的视图中,“添加标签”部分位于“创建”配方之间。 (ListBox 用于“创建”配方)。我看不到如何将一个表单放在另一个表单上,就像您显示的那样,但是将“添加标签”部分插入“创建食谱”表单之间,就像它当前显示在视图上一样。
  • 只有在视觉上来自一个表单的部分/输入堆叠在另一个表单之上并且视觉上没有混合时,我才能看到它工作。
猜你喜欢
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
相关资源
最近更新 更多