Bootstrap-Razor-Model Checkboxes and Radio Button Groups

Update 06/09/2021

I updated KenHaggerty.Com to Bootstrap v5, therefore I updated the demos and the article with Bootstrap v5 markup.

Update 03/07/2019

I updated KenHaggerty.Com to Bootstrap Native and no longer require jQuery, therefore I updated the article with the vanilla JavaScript for the select all checkbox functions.

I have used sprites to make custom checkboxes and radio button groups but it involved a lot of css like span before label and a sprite image with negative positioning. Bootstrap 4 makes this easier to implement even if it may be doing something similar under the hood. What sent me searching was how to get the selected radio button on post. The answer is set each radio value and the asp-for to a model property. If you set the property on get, it will be the default selection. On post, the property equals selected value.

A little bonus. If you want a pointer on hover, add this to css:
Bootstrap v4:
.custom-control-input ~ .custom-control-label {
    cursor: pointer;
}
Bootstrap v5:
.form-check-input, .form-check-input ~ .form-check-label {
    cursor: pointer;
}

Checkboxes

First the model:

public class InputProperties
{
    public string Name { get; set; }
    public string ElementId { get; set; }
    public bool IsSelected { get; set; }
    public bool IsDisabled { get; set; }
}

[BindProperty]
public List<InputProperties> Checkboxes { get; set; }

public void OnGet()
{
    Checkboxes = new List<InputProperties>()
    {
        new InputProperties() { Name = "Debug", ElementId = "CheckboxDebug" },
        new InputProperties() { Name = "Information", ElementId = "CheckboxInformation", IsSelected=true },
        new InputProperties() { Name = "Warning", ElementId = "CheckboxWarning" },
        new InputProperties() { Name = "Error", ElementId = "CheckboxError", IsSelected=true },
        new InputProperties() { Name = "Critical", ElementId = "CheckboxCritical" }
    };
}

Now the razor part:

Bootstrap v4:
<form method='post'>
    <div class='custom-control custom-checkbox custom-control-inline'>
        <input type='checkbox' class='custom-control-input' id='CheckboxSelectAll' />
        <label class='custom-control-label' for='CheckboxSelectAll'>
            Select All
        </label>
    </div>
    @for (var i = 0; i < Model.Checkboxes.Count(); i++)
    {
        <input type='hidden' asp-for='@Model.Checkboxes[i].Name' />
        <div class='custom-control custom-checkbox custom-control-inline'>
            @if (Model.Checkboxes[i].IsDisabled)
            {
                <input class='custom-control-input demo' id='@Model.Checkboxes[i].ElementId' asp-for='Checkboxes[i].IsSelected' disabled />
            }
            else
            {
                <input class='custom-control-input demo' id='@Model.Checkboxes[i].ElementId' asp-for='Checkboxes[i].IsSelected' />
            }
            <label class='custom-control-label' for='@Model.Checkboxes[i].ElementId'>
                @Model.Checkboxes[i].Name
            </label>
        </div>
    }
    <button type="submit" class="btn btn-primary">Post</button>
</form>
Bootstrap v5:
<form method='post'>
    <div class='form-check form-check-inline'>
        <input type='checkbox' class='form-check-input' id='CheckboxSelectAll' />
        <label class='form-check-label' for='CheckboxSelectAll'>
            Select All
        </label>
    </div>
    @for (var i = 0; i < Model.Checkboxes.Count(); i++)
    {
        <input type='hidden' asp-for='@Model.Checkboxes[i].Name' />
        <div class='form-check form-check-inline'>
            @if (Model.Checkboxes[i].IsDisabled)
            {
                <input class='form-check-input demo' id='@Model.Checkboxes[i].ElementId' asp-for='Checkboxes[i].IsSelected' disabled />
            }
            else
            {
                <input class='form-check-input demo' id='@Model.Checkboxes[i].ElementId' asp-for='Checkboxes[i].IsSelected' />
            }
            <label class='form-check-label' for='@Model.Checkboxes[i].ElementId'>
                @Model.Checkboxes[i].Name
            </label>
        </div>
    }
    <button type="submit" class="btn btn-primary">Post</button>
</form>

OnPost():

foreach (var cb in Checkboxes)
{
    if (cb.IsSelected)
    {
        var cbName = cb.Name;
    }
}

Finally the jQuery for Select All:

@section scripts {
    <script>
        $(function () {
            // Set '#CheckboxSelectAll' to checked if all other boxes are already checked
            $('#CheckboxSelectAll').prop('checked', $('.demo').length == $('.demo:checked').length);

            // Add click function to '#CheckboxSelectAll' to select all other boxes
            $('#CheckboxSelectAll').click(function () {
                $('.demo').prop('checked', this.checked);
            });

            // Add click function to each child checkbox
            $('.demo').click(function () {
                $('#CheckboxSelectAll').prop('checked', $('.demo').length == $('.demo:checked').length);
            });
        })
    </script>
}

Section references:

Vanilla JavaScript for Select All:

@section scripts {
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            
            // Check for '#CheckboxSelectAll' exists
            if (document.querySelector('#CheckboxSelectAll')) {

                var demoCheckboxes = document.querySelectorAll('.demo');
                var dcl = demoCheckboxes.length;
                var i = 0;

                // Set '#CheckboxSelectAll' to checked if all other boxes are already checked
                document.querySelector('#CheckboxSelectAll').checked = dcl === document.querySelectorAll('.demo:checked').length;

                // Add click function to '#CheckboxSelectAll' to select all other boxes
                document.querySelector('#CheckboxSelectAll').addEventListener('click', function () {
                    for (i = 0; i < dcl; i++) {
                        demoCheckboxes[i].checked = this.checked;
                    }
                });

                // Add click function to each child  css class demo checkbox
                for (i = 0; i < dcl; i++) {
                    demoCheckboxes[i].addEventListener('click', function () {
                        document.querySelector('#CheckboxSelectAll').checked = dcl === document.querySelectorAll('.demo:checked').length;
                    });
                }
            }
        })
    </script>
}

Radio List

The model:

public class InputProperties
{
    public string Name { get; set; }
    public string ElementId { get; set; }
    public bool IsSelected { get; set; }
    public bool IsDisabled { get; set; }
}

[BindProperty]
public List<InputProperties> RadioButtons { get; set; }

[BindProperty]
public string SelectedRadio { get; set; }

public void OnGet()
{
    RadioButtons = new List()
    {
        new InputProperties() { Name = "Debug", ElementId = "RadioDebug" },
        new InputProperties() { Name = "Information", ElementId = "RadioInformation" },
        new InputProperties() { Name = "Warning", ElementId = "RadioWarning" },
        new InputProperties() { Name = "Error", ElementId = "RadioError" },
        new InputProperties() { Name = "Critical", ElementId = "RadioCritical" }
    };

    SelectedRadio = "Warning";
}

The razor part:

Bootstrap v4:
<form method='post'>
    @for (var i = 0; i < Model.RadioButtons.Count(); i++)
    {
        <div class='custom-control custom-checkbox custom-control-inline'>
            @if (Model.RadioButtons[i].IsDisabled)
            {
                <input type='radio' value='@Model.RadioButtons[i].Name' class='custom-control-input' id='@Model.RadioButtons[i].ElementId'  asp-for='@Model.SelectedRadio' disabled />
            }
            else
            {
                <input type='radio' value='@Model.RadioButtons[i].Name' class='custom-control-input' id='@Model.RadioButtons[i].ElementId'  asp-for='@Model.SelectedRadio' />
            }
            <label class='custom-control-label' for='@Model.RadioButtons[i].ElementId'>
                @Model.RadioButtons[i].Name
            </label>
        </div>
    }
    <button type="submit" class="btn btn-primary">Post</button>
</form>
Bootstrap v5:
<form method='post'>
    @for (var i = 0; i < Model.RadioButtons.Count(); i++)
    {
        <div class='form-check form-check-inline'>
            @if (Model.RadioButtons[i].IsDisabled)
            {
                <input type='radio' value='@Model.RadioButtons[i].Name' class='form-check-input' id='@Model.RadioButtons[i].ElementId'  asp-for='@Model.SelectedRadio' disabled />
            }
            else
            {
                <input type='radio' value='@Model.RadioButtons[i].Name' class='form-check-input' id='@Model.RadioButtons[i].ElementId'  asp-for='@Model.SelectedRadio' />
            }
            <label class='form-check-label' for='@Model.RadioButtons[i].ElementId'>
                @Model.RadioButtons[i].Name
            </label>
        </div>
    }
    <button type="submit" class="btn btn-primary">Post</button>
</form>

OnPost():

var selectedRadio = SelectedRadio;

Article references:
For Bootstrap custom styling. Bootstrap 4 Custom Forms
For Razor Pages. Learn Razor Pages
For code styling in html. JavaScript code prettifier
Ken Haggerty
Created 01/10/19
Updated 06/10/21 02:07 GMT

Log In or Reset Quota to read more.

Article Tags:

Bootstrap BootstrapNative
Successfully completed. Thank you for contributing.
Processing...
Something went wrong. Please try again.
Contribute to enjoy content without advertisments.
You can contribute without registering.

Comments(0)

Loading...
Loading...

Not accepting new comments.

Submit your comment. Comments are moderated.

User Image.
DisplayedName - Member Since ?