【问题标题】:Model Binding editable table fields within a form (Razor Pages)表单中的模型绑定可编辑表字段(Razor 页面)
【发布时间】:2022-01-28 16:52:45
【问题描述】:

我的 Asp.Net 6 - Razor Pages 应用程序在表单中有一个可编辑的表格。

我正在尝试将可编辑的表格字段绑定到模型,但不确定如何执行此操作,因为 td 字段不能与 asp-for 标记助手一起使用。

我希望能够从页面模型的OnPost() 方法中的表中检索已编辑的值。

这些是我要从中检索值的两个可编辑表列的 ID:

  • 对于id="importColumn",当用户单击一个单元格时,该列的单元格值会使用 Javascript on-click 处理程序从勾号更改为叉号。

  • 对于id="modifiedColumnNames",用户修改此列中任何单元格的值。

.cshtml 表单:

<form method="post" asp-antiforgery="true">
   <table id="columnsToImportTable" class="display roundedCorners" width="100%">
      <thead>
         <tr>
            <th class="centreText">Column Name</th>
            <th class="centreText">Import Column</th>
            <th class="centreText">Database Column Name</th>
         </tr>
      </thead>
      <tbody>
         @for (var i = 0; i < Model.newLayer.ColumnNames.Count(); i++)
         {
         <tr>
            <td class="greyOutBackground centreText defaultCursor">@Model.newLayer.ColumnNames[i]</td>
            <td id="importColumn" class="greyOutBackground centreText pointerCursor green tick true">&#10004;
               <input type="hidden" asp-for="@Model.newLayer.ImportColumn[i]" value="true">
            </td>
            <td id="modifiedColumnNames">
               <div contenteditable>@Model.newLayer.ColumnNames[i]</div>
               <input type="hidden" asp-for="@Model.newLayer.ColumnNames[i]">
            </td>
         </tr>
         }
      </tbody>
   </table>
   <div>
      <input id="importButton" type="submit" value="Import">
   </div>
</form>

Javascript/Jquery 点击处理程序:

$('#columnsToImportTable td.tick').click(function(e) {
    e.stopPropagation();
    e.preventDefault();
    var $this = $(this);

    if ($this.hasClass('true')) {
        $this.html('<td id="importColumn" class="greyOutBackground centreText pointerCursor red tick false centreElement">&#10006;<input type="hidden" asp-for="@Model.newLayer.ImportColumn[i]" value="false"></td>');
    } else {
        $this.html('<td id="importColumn" class="greyOutBackground centreText pointerCursor green tick true centreElement">&#10004;<input type="hidden" asp-for="@Model.newLayer.ImportColumn[i]" value="true"></td>');
    }

    $this.toggleClass('true');
});

模特:

public class NewLayer
    {
        public List<string> ColumnNames { get; set; } = new List<string>();
        public List<string> ColumnDataTypes { get; set; } = new List<string>();
        public List<string> LayerNames { get; set; } = new List<string>();
        public List<string> ImportColumn { get; set; } = new List<string>();
        public string SelectedLayer { get; set; } = null!;
        public string SelectedNameField { get; set; } = null!;
    }

页面模型:

public class IndexModel: PageModel {
  private FileProcessor _FileProcessor = new FileProcessor();
  private AppContext _context;

  [BindProperty(SupportsGet = true)]
  public NewLayer newLayer {get;set;}

  public IndexModel(AppContext context) {
    _context = context;
    newLayer = new NewLayer();
  }

  public void OnGet() {
    var filePath = "[FilePath]";

      var ColumnNamesAndDatatypes = _FileProcessor.GetColumnNamesAndTypes(filePath);

      for (var i = 0; i < ColumnNamesAndDatatypes.Count(); i++) {
        newLayer.ColumnNames.Add(ColumnNamesAndDatatypes[i].ColumnName);
        newLayer.ColumnDataTypes.Add(ColumnNamesAndDatatypes[i].DataType);
        newLayer.ImportColumn.Add("true");
      }

      newLayer.LayerNames = _context.Layers.Select(l => l.LayerName).ToList();
  }

  public void OnPost(NewLayer newLayer) {
    var test = this.newLayer;
  }
}

【问题讨论】:

    标签: c# forms asp.net-core html-table razor-pages


    【解决方案1】:

    由于您使用Model Binding方法提交表单并将数据从客户端传输到后端,因此我们应该根据视图模型和索引设置隐藏字段的名称属性。

    importColumn列,当用户点击单元格时,可以使用clone()方法获取importColumn隐藏字段,然后更改其值属性,最后将其添加到新的td元素中.

    modifiedColumnNames列,当用户修改值时,需要将contenteditable div内容复制到隐藏字段。您可以使用 div 的 input 事件。

    可以参考以下代码:

    Html 元素:为 modifiedColumnNames 隐藏字段添加类。

    <form method="post" asp-antiforgery="true">
       <table id="columnsToImportTable" class="display roundedCorners" width="100%">
          <thead>
             <tr>
                <th class="centreText">Column Name</th>
                <th class="centreText">Import Column</th>
                <th class="centreText">Database Column Name</th>
             </tr>
          </thead>
          <tbody>
             @for (var i = 0; i < Model.newLayer.ColumnNames.Count(); i++)
             {
             <tr>
                <td class="greyOutBackground centreText defaultCursor">@Model.newLayer.ColumnNames[i]</td>
                <td id="importColumn" class="greyOutBackground centreText pointerCursor green tick true">&#10004;
                   <input type="hidden" asp-for="@Model.newLayer.ImportColumn[i]" value="true">
                </td>
                <td id="modifiedColumnNames">
                   <div class="editdiv" contenteditable>@Model.newLayer.ColumnNames[i]</div>
                   <input type="hidden" asp-for="@Model.newLayer.ColumnNames[i]">
                </td>
             </tr>
             }
          </tbody>
       </table>
       <div>
          <input id="importButton" type="submit" value="Import">
       </div>
    </form>
    

    JS代码:

    <script>
        $(function(){
            $('#columnsToImportTable td.tick').click(function(e) {
                e.stopPropagation();
                e.preventDefault();
                var $this = $(this);
                // get the ImportColumn hidden field.
                var hiddentag = $(this).find("input[type='hidden']").clone();
                if ($this.hasClass('true')) {
                    //change the hidend field' value 
                    $(hiddentag).attr("value","false");
                    //get the html 
                    var newtag = $(hiddentag)[0].outerHTML;
                    $this.html('<td id="importColumn" class="greyOutBackground centreText pointerCursor red tick false centreElement">&#10006;' + newtag + '</td>');
                } else {
                    $(hiddentag).attr("value","true");
                    var newtag = $(hiddentag)[0].outerHTML;
                    $this.html('<td id="importColumn" class="greyOutBackground centreText pointerCursor green tick true centreElement">&#10004;' + newtag + '</td>');
                }
                $this.toggleClass('true');
            });
            //
            $(".editdiv").each(function(index, item){
                $(item).on('propertychange input', function (e) {
                    $(this).next("input[type='hidden']").val($(this).text());
                });
            });
        });
    </script>
    

    索引.cshtml.cs:

    public class IndexModel : PageModel
    {
        //private FileProcessor _FileProcessor = new FileProcessor();
        //private AppContext _context;
    
        [BindProperty(SupportsGet = true)]
        public NewLayer newLayer { get; set; }
    
        public IndexModel()
        { 
            newLayer = new NewLayer();
        }
    
        public void OnGet()
        { 
            for (var i = 0; i < 3; i++)
            {
                newLayer.ColumnNames.Add("Name " + i.ToString());
                newLayer.ColumnDataTypes.Add("DataType " + i.ToString());
                newLayer.ImportColumn.Add("true");
            }
    
            newLayer.LayerNames = new List<string>() { "L1", "L2" };
        }
    
        public void OnPost(NewLayer newLayer)
        {
            var test = this.newLayer;
        }
    }
    

    结果是这样的:

    【讨论】:

      猜你喜欢
      • 2020-07-02
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 2015-02-25
      • 2019-03-18
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多