如何提交包含带有输入元素的多页表的表单

Posted

技术标签:

【中文标题】如何提交包含带有输入元素的多页表的表单【英文标题】:How to submit form containing multi-page table with input elements 【发布时间】:2015-08-30 12:00:40 【问题描述】:

我在我的表和Datatables.net 上使用引导程序来集成搜索和分页。问题是点击提交按钮后,Model上只保留了Table的当前页面。

没有通过Datatables.net集成搜索和分页,只有使用Datatables.net插件时没有错误。

型号:

public class SampleViewModel

    public List<CollectionViewModel> Collection  get; set; 


public class CollectionViewModel

    public string Name  get; set; 
    public int? Value  get; set; 

控制器:

public ActionResult Sample()

    SampleViewModel model = new SampleViewModel();
    model.Collection = new List<CollectionViewModel>();
    model.Collection.Add(new CollectionViewModel  Name = "Test1" );
    model.Collection.Add(new CollectionViewModel  Name = "Test2" );
    model.Collection.Add(new CollectionViewModel  Name = "Test3" );
    model.Collection.Add(new CollectionViewModel  Name = "Test4" );
    model.Collection.Add(new CollectionViewModel  Name = "Test5" );
    model.Collection.Add(new CollectionViewModel  Name = "Test6" );
    model.Collection.Add(new CollectionViewModel  Name = "Test7" );
    model.Collection.Add(new CollectionViewModel  Name = "Test8" );
    model.Collection.Add(new CollectionViewModel  Name = "Test9" );
    model.Collection.Add(new CollectionViewModel  Name = "Test10" );
    model.Collection.Add(new CollectionViewModel  Name = "Test11" );
    model.Collection.Add(new CollectionViewModel  Name = "Test12" );
    model.Collection.Add(new CollectionViewModel  Name = "Test13" );
    model.Collection.Add(new CollectionViewModel  Name = "Test14" );
    model.Collection.Add(new CollectionViewModel  Name = "Test15" );

    return View(model);


[HttpPost]
public ActionResult Sample(SampleViewModel model)

    var ctr = model.Collection.Count(x => x.Value != null);

    return View(model);

查看:

@model MyApp.Models.SampleViewModel

@using (html.BeginForm())

<div class="dataTable_wrapper">
    <div class="pull-right">
        <button type="submit" name="submitButton" class="btn btn-primary btn-sm">
            <i class="fa fa-floppy-o fa-1x"></i>
            Submit
        </button>
    </div><br /><hr />
    <table class="table table-striped table-bordered table-hover">
        <thead>
            <tr>
                <th>Name</th>
                <th>Value</th>
            </tr>
        </thead>
        <tbody>
             @for (int i = 0; i < Model.Collection.Count(); ++i)
             
                 @Html.HiddenFor(model => model.Collection[i].Name)
                <tr>
                    <td>@Html.DisplayFor(model => model.Collection[i].Name)</td>
                    <td>
                        @Html.TextBoxFor(model => model.Collection[i].Value, new  @class = "form-control" )
                    </td>
                </tr>
             
        </tbody>
    </table>
</div>

提交前:

点击提交按钮后:

您可以在上图中看到,模型上只存储了 15 条记录,而不是 10 条记录

【问题讨论】:

我猜是因为表单上只显示了 10 条记录,所以当您发布时只有它们具有非空值,并且您明确要求 x.Value != null 当使用带有分页的 DataTables 插件时,DOM 中仅存在当前页面 &lt;tr&gt; 元素(在您的示例中为 10)。因此,当您提交表单时,只会提交当前页面表单控件值。 我明白了,所以没有解决方案?也许我不应该使用 Datatables 插件 当然有一个解决方案,但它需要在客户端和服务器端进行额外的编码。 【参考方案1】:

原因

当使用带有分页的 DataTables 插件时,DOM 中仅存在当前页面 &lt;tr&gt; 元素(在您的示例中为 10)以提高性能。因此,当您提交表单时,只会提交当前页面表单控件值。

解决方案 1:直接提交表单

诀窍是在提交表单之前将非当前页面的表单元素转换为&lt;input type="hidden"&gt;

var table = $('#example').DataTable();

// Handle form submission event
$('#frm-example').on('submit', function(e)
   var form = this;

   // Encode a set of form elements from all pages as an array of names and values
   var params = table.$('input,select,textarea').serializeArray();

   // Iterate over all form elements
   $.each(params, function()
      // If element doesn't exist in DOM
      if(!$.contains(document, form[this.name]))
         // Create a hidden element
         $(form).append(
            $('<input>')
               .attr('type', 'hidden')
               .attr('name', this.name)
               .val(this.value)
         );
      
   );
);

有关代码和演示,请参阅this example。

解决方案 2:通过 Ajax 提交表单

另一种解决方案是通过 Ajax 提交表单。

var table = $('#example').DataTable();

// Handle form submission event
$('#frm-example').on('submit', function(e)
   // Prevent actual form submission
   e.preventDefault();

   // Serialize form data
   var data = table.$('input,select,textarea').serialize();

   // Submit form data via Ajax
   $.ajax(
      url: '/echo/jsonp/',
      data: data,
      success: function(data)
         console.log('Server response', data);
      
   );
);

有关代码和演示,请参阅 this example。

注意事项

请注意,这两种解决方案都只能在客户端处理模式下工作。

链接

更多详情请见jQuery DataTables: How to submit all pages form data。

【讨论】:

以上是关于如何提交包含带有输入元素的多页表的表单的主要内容,如果未能解决你的问题,请参考以下文章

表单元素

表单元素

获取包装器的 innerHTML,包括用户在输入元素中输入的值

.NET MVC3 中多页表单的最佳实践/设计

使用对数据库表的查询结果填充 html 表单选择元素

Vuejs - 如何在单个表单中仅提交可见元素(使用 Vuelidate)