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;
Comments(0)