Advanced Ajapa Yoga Kriyas and Meditations for Software Developers : Tap the power of breath, mantra, mudra, and dhyana for improved focus, peace of mind, and blissful inner connection.


Display Checkbox and Radio Button table column in ASP.NET Core

Displaying data in tabular or grid format is quite common in web applications. At times you want to display a column as a series of checkboxes or radio buttons such that a user can indicate a boolean selection. In this article we will discuss a possible approach to accomplish that task.

Before we delve into the code, take a look at the following figure that shows a checkbox column of a simple grid.

As you can see, the table shown in the figure displays a set of TODO items. Each row has Title, StartDate, and EndDate shown in a regular table column. Notice the IsActive column -- it's a boolean value and is displayed as a checkbox.

The IsActive property indicates whether a TODO item is currently being actively worked on. You can have zero or more items active at a given time. In the figure shown above, second and fourth item is currently active as indicated by checkbox selection.

You can select or un-select checkboxes and click on the Submit button to send the new choice to the server.

To begin developing this example, create a new ASP.NET Core MVC application using Visual Studio. And set it up as you normally do.

Now add a new class named ToDo in the Models folder and write the following code in it:

public class ToDo
{
    public int Id { get; set; }
    public string Title { get; set; }    
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public bool IsActive { get; set; }
}    

As you can see, the ToDo class has five properties namely Id, Title, StartDate, EndDate, and IsActive. Most of the properties are self explanatory except IsActive. The IsActive boolean property indicates whether a TODO item is currently being actively worked upon or not.

For our first example we are going to assume that at a time multiple TODO items can be active (IsActive = true) so that we get chance to use checkboxes to toggle their selection.

Next, add HomeController to the Controllers folder. And write the Index() action as shown below:

public IActionResult Index()
{
    List<ToDo> items= new List<ToDo>();
    items.Add(new ToDo
    {
        Id = 1,
        Title = "ToDo Title 1",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = false
    });
    items.Add(new ToDo
    {
        Id = 2,
        Title = "ToDo Title 2",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = true
    });
    items.Add(new ToDo
    {
        Id = 3,
        Title = "ToDo Title 3",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = false
    });
    items.Add(new ToDo
    {
        Id = 4,
        Title = "ToDo Title 4",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = true
    });
    items.Add(new ToDo
    {
        Id = 5,
        Title = "ToDo Title 5",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = false
    });
    return View(items);
}

The Index() action simply creates five ToDo objects and adds them to a List. Notice that objects with Id 2 and 4 have their IsActive property set to true. This List is them passed to the Index view through the View() method.

Now add Views -- Home -- Index.cshtml view file and write the following markup and code to it.

@model List<ToDo>;

<form asp-controller="Home" asp-action="SubmitCheckBox">

    <h1>Checkbox Column Demo</h1>

    <table cellpadding="10" border="1">
        <tr>
        <th align="center">Is Active</th>
        <th>Title</th>
        <th>Start Date</th>
        <th>End Date</th>
        </tr>
        @for (var i = 0; i < @Model.Count; i++)
        {
            <tr>
            <td align="center">
                <input type="checkbox" 
                    asp-for="@Model[i].IsActive" />
                <input type="hidden" asp-for="@Model[i].Id" />
                </td>
                <td>
                    @Model[i].Title
                    <input type="hidden" 
                    asp-for="@Model[i].Title" />
                </td>
                <td>
                    @Model[i].StartDate.ToShortDateString()
                    <input type="hidden" 
                    asp-for="@Model[i].StartDate" />
                </td>
                <td>
                    @Model[i].EndDate.ToShortDateString()
                    <input type="hidden" 
                    asp-for="@Model[i].EndDate" />
                </td>
            </tr>
        }
    </table>
    <br />
    <button type="submit">Submit</button>
    <h2>@Html.Raw(ViewData["message"])</h2>
</form>

Let's examine the code carefully.

We begin by specifying the model for the view -- a List of ToDo objects. Then there is a form that POSTs to the SubmitCheckBox() action of the HomeController. We will write the SubmitCheckBox() POST action later in this article.

The form houses a table that displays all the ToDo items. To render this table we run a for loop that iterates through the List<ToDo>.

Notice all the columns of the table. The first column displays a checkbox using an input element. The type attribute is set to checkbox and asp-for attribute is set to @Model[i].IsActive. Setting the asp-for attribute ensures that the name, id, and value of the checkbox element is generated properly as expected by the ASP.NET Core model binder.

The first column also stores an Id in a hidden form field. When a form is submitted to the server, only form field values get submitted. If you don't store Id in a hidden form field, it won't be submitted to the server and we won't be able to identity the ToDo object bound with this row.

On the similar lines, the second, third, and fourth columns of the table display Title, StartDate, and EndDate properties. We also store these property values in the respective hidden fields.

At the bottom of the form there is a submit button. Just after the form, we display ViewData["message"] containing the result of the submit operation.

If you load this form in the browser you will see this HTML table being generated in the browser:

    <tr>
    <td align="center">
        <input type="checkbox" 
            data-val="true" 
            data-val-required="The IsActive field is required." 
            id="z0__IsActive" 
            name="[0].IsActive" 
            value="true" />
            <input type="hidden" 
            data-val="true" 
            data-val-required="The Id field is required." 
            id="z0__Id" name="[0].Id" 
            value="1" />
        </td>
        <td>
            ToDo Title 1
            <input type="hidden" 
            id="z0__Title" 
            name="[0].Title" 
            value="ToDo Title 1" />
        </td>
        <td>
            15-01-2023
            <input type="hidden" 
            data-val="true" 
            data-val-required="The StartDate field is required." 
            id="z0__StartDate" 
            name="[0].StartDate" 
            value="15-01-2023 00:00:00" />
        </td>
        <td>
            15-11-2023
            <input type="hidden" 
            data-val="true" 
            data-val-required="The EndDate field is required." 
            id="z0__EndDate" 
            name="[0].EndDate" 
            value="15-11-2023 00:00:00" />
        </td>
    </tr>

Notice the code shown in bold letters. The name attribute is generated in a specific way so that ASP.NET Core model binder can re-generate List of ToDo objects upon form submission. The above markup is for the first data row. Hence, the index is 0. For other rows similar names will be generated based on the index.

Now that our Index view is over, let's add the Index() POST method that processes the submitted form.

[HttpPost]
public IActionResult SubmitCheckBox(List<ToDo> items)
{
    ViewData["message"] = "You selected : ";
    foreach (var item in items)
    {
        if(item.IsActive)
        {
            ViewData["message"] += item.Id + "  ";
        }
    }
    return View("Index", items);
}

The SubmitCheckBox() action takes a List<ToDo> as its parameter. Inside, we run a for loop that iterates through the List. We check the IsActive property of each item. If IsActive is true we append that item's Id to ViewData["message"]. Finally, the Index view is rendered again.

Run the application, select a few checkboxes and click on the submit button. The following figure shows a sample run of the application.

So far so good. In this example we rendered a checkbox column in our table. What if we want to display a radio button column? Say, at a time only one ToDo item can be active and hence you want to set IsActive via radio buttons instead of checkboxes. Of course, you can do that on the similar lines. But there will be a few differences.

Firstly, a radio button column needs to act as a single group. That means all the radio buttons displayed in a column must have the same name. Moreover, you need to ensure that only one ToDo object can have IsActive set to true because the selection is now through radio buttons and only one radio button from the column can be selected.

Take a look at the following figure that shows a grid with radio button column.

Let's modify our example to use radio buttons instead of checkboxes.

Firstly, go to the Index() action and ensure that only one ToDo object has IsActive set to true.

public IActionResult Index()
{
    List<ToDo> items= new List<ToDo>();
    items.Add(new ToDo
    {
        Id = 1,
        Title = "ToDo Title 1",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = false
    });
    items.Add(new ToDo
    {
        Id = 2,
        Title = "ToDo Title 2",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = true
    });
    items.Add(new ToDo
    {
        Id = 3,
        Title = "ToDo Title 3",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = false
    });
    items.Add(new ToDo
    {
        Id = 4,
        Title = "ToDo Title 4",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = true
    });
    items.Add(new ToDo
    {
        Id = 5,
        Title = "ToDo Title 5",
        StartDate = new DateTime(2023, 1, 15),
        EndDate = new DateTime(2023, 11, 15),
        IsActive = false
    });
    return View(items);
}

Note that ToDo item with Id of 4 has IsActive set to true indicating that it's the active item.

Now open Index.cshtml and modify the form as shown below. You can keep a copy of the earlier form for your reference.

@model List<ToDo>;

<form asp-controller="Home" asp-action="SubmitRadioButton">

    <h1>Radio Button Column Demo</h1>

    <table cellpadding="10" border="1">
        <tr>
        <th align="center">Is Active</th>
        <th>Title</th>
        <th>Start Date</th>
        <th>End Date</th>
        </tr>
        @for (var i = 0; i < @Model.Count; i++)
        {
            <tr>
            <td align="center">
                
                <input type="radio" 
                name="IsActiveRadioGroup" 
                value="@Model[i].Id" 
                id="@Model[i].Id" 
                checked="@Model[i].IsActive" />
                <input type="hidden" asp-for="@Model[i].Id" />
                <input type="hidden" asp-for="@Model[i].IsActive" />
                
                </td>
                <td>
                    @Model[i].Title
                    <input type="hidden" 
                    asp-for="@Model[i].Title" />
                </td>
                <td>
                    @Model[i].StartDate.ToShortDateString()
                    <input type="hidden" 
                    asp-for="@Model[i].StartDate" />
                </td>
                <td>
                    @Model[i].EndDate.ToShortDateString()
                    <input type="hidden" 
                    asp-for="@Model[i].EndDate" />
                </td>
            </tr>
        }
    </table>
    <br />
    <button type="submit">Submit</button>
    <h2>@Html.Raw(ViewData["message"])</h2>
</form>

The form submits to the SubmitRadioButton() action. You will write the SubmitRadioButton() later in this article.

Notice the code shown in bold letters. All the radio button elements have a common name -- IsActiveRadioGroup. This way ony one of them can be selected at a time. The value attribute of the radio button is set to the Id of the ToDo item. This will be helpful in deciding the selected radio button upon form submission. The checked attribute is set to the value of IsActive property. This is required to set the selected radio button when the page is initially loaded. The checked attribute is outputted only if its value is true. So, in our example checked will be outputted only for ToDo item whose Id is 4. A sample radio button markup generated is shown below:

<input type="radio" 
name="IsActiveRadioGroup" 
value="4" 
id="4" 
checked="checked" />

This time we store Id as well as IsActive in hidden fields so that model binder can use them to fill a List upon form submission.

The other table columns are quite similar to the checkbox example discussed earlier.

Now go to the HomeController and add the SubmitRadioButton() action as shown below:

[HttpPost]
public IActionResult SubmitRadioButton
(List<ToDo> items, int IsActiveRadioGroup)
{
    foreach(var item in items)
    {
        item.IsActive = 
        (item.Id == IsActiveRadioGroup ? true:false);
    }
    ViewData["message"] = "You selected : " 
    + IsActiveRadioGroup;
    return View("Index", items);
}    

The SubmitRadioButton() action takes two parameters -- List<ToDo> and IsActiveRadioGroup. The IsActiveRadioGroup parameter indicates the value of the selected radio button. Recollect that we have set value to the Id property and hence IsActiveRadioGroup will be the Id of a ToDo item that we want to make active.

Inside, we iterate through the List and set the IsActive property of the ToDo item to true whose Id is equal to IsActiveRadioGroup.

The following figure shows a sample run of the application.

This way we can display a grid column in the form of checkboxes or radio buttons.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a meditation teacher and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his ASP.NET online courses go here. More details about his Ajapa Japa and Shambhavi Mudra online course are available here.

Posted On : 29 May 2023







Advanced Ajapa Yoga Kriyas and Meditations for Software Developers : Tap the power of breath, mantra, mudra, and dhyana for improved focus, peace of mind, and blissful inner connection.