'Model Binding editable table fields within a form (Razor Pages)

My Asp.Net 6 - Razor Pages application has an editable table within a form.

I am trying to bind the editable table fields to a model but am not sure how to do so because td fields cannot be used with asp-for tag helpers.

I want to be able to retrieve the edited values from the table in the Page Model's OnPost() method.

These are the ids of the two editable table columns that I want to retrieve the values from:

  • For id="importColumn", when a user clicks on a cell, the cell value for this column gets changed from a tick to a cross using a Javascript on-click handler.

  • For id="modifiedColumnNames", the user modifies the value of any cell within this column.

.cshtml Form:

<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 click handler:

$('#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');
});

The Model:

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!;
    }

The Page Model:

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;
  }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source