The customer wants to be able to go to a page and put a number next to the column name to identify which position from left to right that they want to view the columns.
Assign a short column id/name to each column selected by the user.
Plan Name column -> "plan" or Date Joined column -> "joined"
The column id can be a data attribute on a div
representing a column on the client.
<div class="col" data-col-id="joined">
On the client side, build a string of the user's column order selection.
"plan,joined,name"
On the client side, create a query string containing of the user's column order and pass this to the server when you're checking for new records (or pass this string in the request header or whatever mechanism available to pass data from the client to the serve in the fetch
API).
"?colorder=plan,joined,name"
Each string segment in the query string value is associated with each customer class property using a custom attribute.
[ColQueryName("joined")]
public DateOnly DateJoined { get; set; }
On the server, store the column order query string in your user database (commonly as a view state table for each user's client-side view state preferences).
public class UserViewState
{
public string UserId { get; set; }
public string ColumnOrder { get; set; } // Customer column order preference
}
When retrieving data on the server, parse the column order string and create a table data model based on the column order.
List<Column> columns = new();
// E.g. customer.ColumnOrder = "joined,name,plan"
string[] columnNamesArr = customer.ColumnOrder
.Split(',', StringSplitOptions.RemoveEmptyEntries);
// E.g. columnNamesArr = ["joined", "name", "plan"]
foreach (string columnName in columnNamesArr)
{
string colName = columnName.Trim();
PropertyInfo? propInfo = GetPropInfo(colName);
// E.g. propInfo?.GetValue(customer)
// -> customer.DateJoined = "8/25/2022"
string? propValue = propInfo?.GetValue(customer)?.ToString();
// Add a new 'Column' object to the list of columns
columns.Add(new Column() { Name = colName, Value = propValue });
}
// Create a 'TableData' object
TableData tableData = new() { Columns = columns };
Pass the table data model to a Razor partial view to build the HTML containing the table.
Customer customer = @Model.Customer;
TableData? tableData = @Model.TableData;
<h3>@user.Name</h3>
<span class="column-order-val">
Column order » <span>@userViewState.ColumnOrder</span>
</span>
<div class="customer-table">
@foreach (Column column in tableData.Columns)
{
<div class="col @column.Name.Trim().ToLower()">
<span class="col-header"></span>
<span class="col-cell">@column.Value</span>
</div>
}
</div>
This Stack Overflow post provides a class to do this.
partialViewHtml = await this.RenderViewAsync("_ColumnOrder", tableData, true);
Return the partial view as a string back to the client to be rendered to the user.
Here's a sample output of the above steps (minus the partial view HTML). The results are rendered as a separate Razor page.
