0

I'm a bit lost on how to implement HTML column display based on how the user wishes to view the content.

I have a table of customer information that is updated regularly and I poll the database with an ajax request every 2 minutes to check for new records. I initially build this functionality using drag and drop tables, however, the view jumps/flickers on refresh once a column is moved and that is causing vision difficulty for some users. Therefore, I need to build the layout server side and present it to them without the jump/flickering.

My truncated model is;

public class Customer
{
    public string UserId { get; set; }
    public string Name { get; set; }
    public DateTime DateJoined { get; set; }
    public string PlanName { get; set; }  
}

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. An example based on the truncated view might be;

DateJoined Name PlanName
One Two Three

or

Name PlanName DateJoined
One Two Three

Or any other combinations

I would appreciate any thoughts on how you would do this from both storing the user preferences and then building the view, such as a table perhaps.

Dave
  • 135
  • 7

1 Answers1

1

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 &#187; <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.

enter image description here

Dave B
  • 1,105
  • 11
  • 17