ASP.NET Core 2.2 - Bootstrap 4 Tables


Ken Haggerty
Created 08/17/2019 - Updated 08/25/2019 16:00

This article will demonstrate some of the Bootstrap 4 table css classes I will use in upcoming articles about table functions. I will assume you have created a new ASP.NET Core 2.2 Razor Pages project. I won't use Identity or Individual User Accounts.

The research project I used for the articles about table functions is published to tables.kenhaggerty.com. I created a topic, ASP.NET Core 2.2 - Table Functions Project for discussions. Access to the source code may be purchased at Manage > Assets.

After you have implemented In Memory Entities, the entities are dynamically displayed in a simple Razor/Bootstrap table. A few table classes like table-hover, table-striped and table-sm can improve the presentation. Although the table is responsive, entities with many properties can crowd small screens. If you offer a details page, you can hide columns on Bootstrap beakpoints.

Let's start with the Food class. You can add DataAnotations to modify the DisplayNameFor property and format the date.

Edit Food.cs, add DataAnotations:
public class Food
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    [Display(Name = "Food Type")]
    public FoodType FoodType { get; set; }
    [Display(Name = "Store Cold")]
    public bool ColdStore { get; set; }
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy hh:mm tt}")]
    public DateTime Date { get; set; }
}

There are plenty of articles about the table classes. I like the table-sm class because it displays more data per window. The table-striped class is applealing but has the same backgroud color as the table-hover class. The table-striped class applies a .05 opacity to odd rows and the table-hover applies a .075 opacity.

Edit Index.cshtml, add the table, th and td classes:
<div class="row">
    <div class="col-12">
        <table class="table table-sm table-striped table-hover border-bottom">
            <thead>
                <tr>
                    <th class="d-none d-lg-table-cell">
                        @Html.DisplayNameFor(model => model.Foods[0].Id)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].FoodType)
                    </th>
                    <th class="d-none d-md-table-cell text-center">
                        @Html.DisplayNameFor(model => model.Foods[0].ColdStore)
                    </th>
                    <th class="d-none d-lg-table-cell">
                        @Html.DisplayNameFor(model => model.Foods[0].Date)
                    </th>
                </tr>
            </thead>
            <tbody>
                @if (Model.Foods.Count > 0)
                {
                    foreach (var item in Model.Foods)
                    {
                        <tr>
                            <td class="d-none d-lg-table-cell">
                                @Html.DisplayFor(modelItem => item.Id)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Name)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.FoodType)
                            </td>
                            <td class="custom-control custom-checkbox text-center d-none d-md-table-cell">
                                <input type="checkbox" asp-for="@item.ColdStore">
                                <input type="checkbox" class="custom-control-input disabled" asp-for="@item.ColdStore">
                                <label class="custom-control-label disabled">
                                    <span class="sr-only">Never</span>
                                </label>
                            </td>
                            <td class="d-none d-lg-table-cell">
                                @Html.DisplayFor(modelItem => item.Date)
                            </td>
                        </tr>
                    }
                }
                else
                {
                    <tr>
                        <td colspan="5" class="text-center">
                            No Food Found
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</div>

You can override the colors of the striped and hover table row classes to provide more contrast.

Edit site.css, add Bootstrap overrides:
.table-striped > tbody > tr:nth-child(2n+1) > td, .table-striped > tbody > tr:nth-child(2n+1) > th {
    background-color: lightgray;
}

.table-hover tbody tr:hover td, .table-hover tbody tr:hover th {
    background-color: gray;
    color: white;
}

You can add a details page to display the hidden columns on small screens. Right click on the Pages folder to add a new page.

Add Razor Page Menu
Razor Page Using Entity Framework
Add Razor Page Using Entity Framework

You can add the custom checkbox and remove the Edit link on the Details page.

Edit Details.cshtml:
<div>
    <h4>Food</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Food.Name)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Food.Name)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Food.FoodType)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Food.FoodType)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Food.ColdStore)
        </dt>
        <dd class="col-sm-10">
            <div class="custom-control custom-checkbox">
                <input type="checkbox" class="custom-control-input" asp-for="@Model.Food.ColdStore">
                <label class="custom-control-label">
                    <span class="sr-only">Never</span>
                </label>
            </div>
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Food.Date)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Food.Date)
        </dd>
    </dl>
</div>
<div>
    <a asp-page="./Index">Back to List</a>
</div>

Add an Actions column to the table with a link to the Details page.

Edit Index.cshtml, add the column:
<div class="row">
    <div class="col-12">
        <table class="table table-sm table-striped table-hover border-bottom">
            <thead>
                <tr class="d-none d-lg-table-cell">
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].Id)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].FoodType)
                    </th>
                    <th class="d-none d-md-table-cell text-center">
                        @Html.DisplayNameFor(model => model.Foods[0].ColdStore)
                    </th>
                    <th class="d-none d-lg-table-cell">
                        @Html.DisplayNameFor(model => model.Foods[0].Date)
                    </th>
                    <th>
                        Actions
                    </th>
                </tr>
            </thead>
            <tbody>
                @if (Model.Foods.Count > 0)
                {
                    @foreach (var item in Model.Foods)
                    {
                        <tr>
                            <td class="d-none d-lg-table-cell">
                                @Html.DisplayFor(modelItem => item.Id)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Name)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.FoodType)
                            </td>
                            <td class="custom-control custom-checkbox text-center d-none d-md-table-cell">
                                <input type="checkbox" asp-for="@item.ColdStore">
                                <input type="checkbox" class="custom-control-input disabled" asp-for="@item.ColdStore">
                                <label class="custom-control-label disabled">
                                    <span class="sr-only">Never</span>
                                </label>
                            </td>
                            <td class="d-none d-lg-table-cell">
                                @Html.DisplayFor(modelItem => item.Date)
                            </td>
                            <td>
                                <a asp-page="/Details" asp-route-id="@item.Id">Details</a>
                            </td>
                        </tr>
                    }
                }
                else
                {
                    <tr>
                        <td colspan="6" class="text-center">
                            No Food Found
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</div>

Build, run and test.

Formatted Table Desktop
Details Page
Formatted Table Mobile
Update 08/20/2019

Updated the link to the previous article in the series.

Update 08/25/2019

Updated articles, asset and topic links.



Comment Count = 0

Please log in to comment or follow.

Login Register
Follow to get web notifications when new comments are posted to this article.
Logged in users receive web notifications for new articles, topics and assets.
Web Notifications