如何获取从视图表传递到控制器的 ID 和所选下拉列表值的集合

How to get collection of IDs, and Selected Dropdown values passed from View's table to Controller?

本文关键字:ID 控制器 集合 下拉列表 获取 何获取 视图      更新时间:2023-09-26

所以我有一个清单/任务管理器类型的应用程序,它基本上使用模型从数据库中提取一堆字符串值,然后将其管道传输到使用展开/折叠模式表的视图。最终用户修饰符超出展开/折叠状态的唯一元素是项目状态的 dopdown 列表。

客户希望页面底部基本上有一个按钮来更新用户更改的所有行,而不是每行都有一个更新按钮。所以我的目标是尝试创建所述按钮。就视图代码片段而言,我尝试过弄乱Html.BeginForm,但也无法弄清楚如何捕获多个项目ID:

@using (Html.BeginForm("UpdateDB", "Checklist", new { id = model.ID })) // model does not exist in this current context
{
<table id="checklistGrid" class="table table-bordered table-striped grid">
    <tr>
        <th>@Html.DisplayNameFor(model => model.ww)</th>
        .... // more table headers
    </tr>
    @foreach (var group in Model.GroupBy(x => x.ww))
        {
        <tr class="group-header">
            <td colspan="12">
                <span class="h2">@group.Key</span>
            </td>
        </tr>
        foreach (var dept in group.GroupBy(x => x.dept))
        {
            <tr class="dept-header">
                <td colspan="12">
                    <span class="h4">@dept.Key</span>
                </td>
            </tr>
            foreach (var item in dept)
            {
                <tr class="row-header">
                    <td> @Html.HiddenFor(modelItem => item.ID)</td>
                    <td>@Html.DisplayFor(modelItem => item.ww)</td>
                    .... // more table columns
                    <td>
                        @{
                            List<string> ddl = new List<string> { "Done", "Not Done", "N/A" };
                            SelectList sl = new SelectList(ddl, item.status);
                            @Html.DropDownList("newStatus", sl); // Added
                        }
                    </td>
                    <td>@Html.DisplayFor(modelItem => item.applied_by)</td>
                    <td>
                        @{
                            DateTime tmp;
                            //Check if not null, if not null convert to specified time zone
                            if (DateTime.TryParse(item.timestamp.ToString(), out tmp))
                            {
                                tmp = item.timestamp ?? DateTime.MinValue;
                                string zoneName = "India Standard Time";
                                var abbrZoneName = TimeZoneNames.TimeZoneNames.GetAbbreviationsForTimeZone(zoneName, "en-US");
                                TimeZoneInfo zoneInfo = TimeZoneInfo.FindSystemTimeZoneById(zoneName);
                                DateTime istTime = TimeZoneInfo.ConvertTimeFromUtc(tmp, zoneInfo);
                                @Html.Raw(istTime.ToString() + " (" + abbrZoneName.Generic + ")");
                            }
                            else
                            {
                                @Html.DisplayFor(modelItem => item.timestamp);
                            }
                        }
                    </td>
                </tr>
            }
        }
    }
</table>
<p><input type="submit" value="Save Changes" /></p>
}
<script type="text/javascript">
    // Hide/Show Dept's Data on Click
    $(function () {
        $('.dept-header').click(function () {
            $(this).nextUntil('.dept-header, .group-header').toggle();
        });
    });
    $(function () {
        $('.group-header').click(function () {
            var elm = $(this);
            if (elm.next().is(":visible")) {
                elm.nextUntil('.group-header').hide();
            } else {
                elm.nextUntil('.group-header', '.dept-header').show();
            }
        });
    });
</script>

我怀疑更简单(计算上更快的方法(是使用 Jquery + Ajax &&Json 附加到底部的按钮上,将 id 和选定的下拉文本集合发送到Controller中的ActionResult(然后更新数据库(,然后在成功的 Ajax 回调时刷新。然而,我的 Jquery/Javascript foo 很弱,并且考虑到可点击的"标题"类型行可以展开/折叠数据行,我不清楚如何有效地使用 Jquery 来导航和抓取item.ID和每行中的选定下拉文本,将其捆绑起来,并通过管道传输到所需的 ActionResult。

那么,如何将所有行的 id 和选定的下拉文本发送到任意ActionResult无论是使用 Html.BeginForm 还是 Jquery 等?

编辑:参考模型:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace TaskTracker.Models
{
    [Table("some_update")]
    public class TaskInfo
    {
        public int ID { get; set; }
        [Display(Name = "WW")]
        public int ww { get; set; }
        [Display(Name = "File Name")]
        public string filename { get; set; }
        [Display(Name = "Dept")]
        public string hsd_unit { get; set; }
        [Display(Name = "Owner")]
        public string owner { get; set; }
        [Display(Name = "Manager")]
        public string manager { get; set; }
        [Display(Name = "Project")]
        public string project { get; set; }
        [Display(Name = "Status")]
        public string status { get; set; }
        [Display(Name = "Last Applied By")]
        public string applied_by { get; set; }
        [Display(Name = "Last Updated Time Stamp")]
        public DateTime? timestamp { get; set; }
    }
    public class TaskInfoDBContext : DbContext
    {
        public DbSet<TaskInfo> TaskInfoSet { get; set; }
    }
}

您在查看时遇到了许多问题,包括表单控件具有重复的name属性,这意味着您在提交时无法绑定到模型,重复id无效 html 的属性,以及您创建一个名称甚至不是模型属性的下拉列表。此外,在视图代码中使用查询不是很好的做法。所有这些都可以通过使用视图模型并使用for循环(而不是foreach循环(或自定义EditorTemplate正确生成html来解决。但是,由于您已经指示了对 ajax 的首选项,因此可以通过对视图进行以下更改来发布数据

替换以下 HtmlHelper 方法

@Html.HiddenFor(modelItem => item.ID)
@Html.DropDownList("newStatus", sl)

@Html.HiddenFor(modelItem => item.ID, new { id = "", @class = "id" })
@Html.DropDownList("Status", sl, new { id = "", @class = "status" })

这将删除无效的id属性并添加类名以供选择。然后将提交按钮替换为

<button type="button" id="save">Save Changes</button>

并添加以下脚本

var rows = $('.row-header'); // store all the table rows containing the form controls
$('#save').click(function() {
  // Build an array of the values to post back
  var data = [];
  $.each(rows, function() {
    data.push({id: $(this).find('.id').val(), status: $(this).find('.status').val() });
  });
  $.ajax({
    url: '@Url.Action("UpdateDB", "Checklist")',
    type: "POST",
    data: JSON.stringify({ model: data },
    traditional: true,
    contentType: "application/json; charset=utf-8",
    success: function(data) {
      // do something?
    }
  })
});

然后创建一个模型来接受这些值

public class TaskInfoUpdate
{
  public int ID { get; set; }
  public string Status { get; set; }
}

并将您的 POST 方法修改为

[HttpPost]
public ActionResult UpdateDB(IEnumerable<TaskInfoUpdate> model)

旁注:不清楚你所说的"然后在成功的 Ajax 回调时刷新">是什么意思(有什么要刷新的?我建议该方法返回return Json(true);如果项目已成功保存,或者return Json(null);(或HttpStatusCodeResult(如果不能,以便您可以根据需要通知用户。