ASP.NET Core 2.2 - Bootstrap Without jQuery


Ken Haggerty
Created 03/27/2019 - Updated 03/27/2019 16:22

This article will cover adding the Bootstrap Native JavaScript library and removing the jQuery libraries for ASP.NET Core. I will assume you have created a new ASP.NET Core 2.2 Razor Pages project with Individual User Accounts, updated the database with the CreateIdentitySchema migration, scaffolded the Identity UI and configured libman.json.

Let's start by loading the Bootstrap Native and Html5shiv libraries.

Edit libman.json, add bootstrap.native and html5shiv libraries:
{
  "library": "bootstrap.native@2.0.25",
  "files": [
    "bootstrap-native-v4.js",
    "bootstrap-native-v4.min.js",
    "polyfill.js",,
    "polyfill.min.js"
  ],
  "destination": "wwwroot/lib/bootstrap/dist/js/"
},
{
  "library": "html5shiv@3.7.3",
  "files": [
    "html5shiv.js",
    "html5shiv.min.js"
  ],
  "destination": "wwwroot/lib/html5shiv/dist/js/"
}

Verify the files are downloaded.

Edit _Layout.cshtml, add polyfill.min.js and html5shiv.min.js inside the head tag just after site.css:
<script src="~/lib/bootstrap/dist/js/polyfill.min.js"></script>
<!--[if lt IE 9]>
    <script src="~/lib/html5shiv/dist/js/html5shiv.min.js"></script>
<![endif]-->
Edit _Layout.cshtml > include="Development" environment tag, comment and add:
<environment include="Development">
    @*<script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>*@
    <script src="~/lib/bootstrap/dist/js/bootstrap-native-v4.js"></script>
</environment>
Edit Index.cshtml, add a Tooltip button:
<div class="row mb-2">
    <div class="col-12">
        <button type="button" class="btn btn-primary" data-toggle="tooltip" title="This is tooltip title attribute turned into a Tooltip">Tooltip</button>
    </div>
</div>

Build, run, open (Chrome) DevTools and refresh the page.

Collapse Error

The tooltip is just the title attribute without styling and the collapsed menu toggle doesn't expand. This is caused by the getTarget function which looks for an element id in the data-target attribute for a data-toggle="collapse" element. The default navbar uses a class name for the data-target.

bootstrap-native-v4.js > getTarget():
getTarget = function() {
    var href = element.href && element[getAttribute]('href'),
        parent = element[getAttribute](dataTarget),
        id = href || ( parent && parent.charAt(0) === '#' ) && parent;
    return id && queryElement(id);
};

Rather than modifying the getTarget function, edit the navbar's data-target attribute.

Edit _Layout.cshtml > navbar, add id to navbar-collapse div and edit the data-target:
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#NavBarCollapse" aria- 
   controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span>
</button>
<div id="NavBarCollapse" class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">

The tooltip is automatically initialized and there are no JavaScript errors.

Collapse Error Fixed

Most of the Bootstrap Native components function the same as Bootstrap with jQuery if you use the data attributes.

Edit Index.cshtml, add Bootstrap button and Bootstrap modal:
<div class="row mb-2">
    <div class="col-12">
        <button type="button" class="btn btn-primary" data-toggle="tooltip" title="This is tooltip title attribute turned into a Tooltip">Tooltip</button>
        <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#BootstrapModalId" >Open Modal</button>
    </div>
</div>

<div id="BootstrapModalId" class="modal" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Modal Test</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                This is a demonstration of Bootstrap Native's modal.
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary btn-update">Update</button>
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
            </div>
        </div>
    </div>
</div>
Data-Toggle Modal

If you want to trigger the modal with JavaScript, you need to initialize it.

Edit Index.cshtml, add a button without data attributes:
<button id="JSOpenModalButtonId" type="button" class="btn btn-primary" >JS Open Modal</button>
Edit Index.cshtml, add JavaScript:
@section Scripts {
    <script>
        var modalInstance = new Modal(document.querySelector('#BootstrapModalId'));

        document.addEventListener('DOMContentLoaded', function () {

            document.querySelector('#JSOpenModalButtonId').addEventListener('click', function () {
                document.querySelector('.modal-body').textContent
                    = 'This is a demonstration of a JavaScript modal.';
                modalInstance.show();
            });

            document.querySelector('.btn-update').addEventListener('click', function () {
                // Do some update.
                document.querySelector('.modal-body').textContent
                    = 'This is a demonstration of Bootstrap Native\'s modal.';
                modalInstance.hide();
            });

        });
    </script>
}

The only other major difficulty I found was closing alert-dismissible classes and the _StatusMessage partial. The _StatusMessage partial is used by Identity > Accounts > Mange and I use them for administration. Copy _StatusMessage.cshtml from Identity > Accounts > Mange to Pages > Shared.

Edit Index.cshtml, add an alert-dismissible class and a _StatusMessage partial:
<div class="row mb-2">
    <div class="col-12">
        <div class="alert alert-secondary alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
            This is an alert-dismissible messagge from page html.
        </div>
        <partial name="_StatusMessage" for="StatusMessage" />
        <form class="form-group d-inline" method="post" asp-page-handler="ShowStatusMessage">
            <button type="submit" class="btn btn-primary">Post Status Message</button>
        </form>
    </div>
</div>
Edit Index.cshtml.cs, add a StatusMessage property and a ShowStatusMessage page handler:
[TempData]
public string StatusMessage { get; set; }
        
public void OnGet()
{
}

public IActionResult OnPostShowStatusMessage()
{
    StatusMessage = "Error: This is a demonstration of a Status Message.";

    return RedirectToPage();
}

Build, run and test the page. The alerts won't close. Rather than initializing the alerts to close them, I use a site.js event handler for the alert close button.

Edit site.js, add the event listener:
document.addEventListener('DOMContentLoaded', function () {

    // Bootstrap-Native Alert close for status messages
    if (document.querySelector('.close.statusmessage')) {
        var alertButtons = document.querySelectorAll('.close.statusmessage');
        var abl = alertButtons.length;
        for (b = 0; b < abl; b++) {
            alertButtons[b].addEventListener('click', function (event) {
                // For SPAN is clickable
                var alertDiv = event.target.parentNode.parentNode;
                // For Firefox and Opera
                if (event.target.nodeName === 'BUTTON') {
                    alertDiv = event.target.parentNode;
                }
                var parent = alertDiv.parentNode;
                parent.removeChild(alertDiv);
            });
        }
    }

});

Add the statusmessage class to the close button in the alert-dismissible classes and the _StatusMessage partials, don't forget the _StatusMessage partial in Identity > Accounts > Mange. Build, run and test the page.

Since we have dealt with the major issues I've found, it's time to remove jQuery. If you remove jQuery, you must remove jquery-validate and jquery-validation-unobtrusive. This jQuery validation is mostly used in Identity. The Password Requirements and Identity Model Validation articles help mitigate the lack of client-side validation.

Edit libman.json, remove the bootstrap js files and the jquery, jquery-validate and jquery-validation-unobtrusive libraries:
{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
    {
      "library": "twitter-bootstrap@4.3.1",
      "files": [
        "css/bootstrap-grid.css",
        "css/bootstrap-grid.css.map",
        "css/bootstrap-grid.min.css",
        "css/bootstrap-grid.min.css.map",
        "css/bootstrap-reboot.css",
        "css/bootstrap-reboot.css.map",
        "css/bootstrap-reboot.min.css",
        "css/bootstrap-reboot.min.css.map",
        "css/bootstrap.css",
        "css/bootstrap.css.map",
        "css/bootstrap.min.css",
        "css/bootstrap.min.css.map"
      ],
      "destination": "wwwroot/lib/bootstrap/dist/"
    },
    {
      "library": "bootstrap.native@2.0.25",
      "files": [
        "bootstrap-native-v4.js",
        "bootstrap-native-v4.min.js",
        "polyfill.js",
        "polyfill.min.js"
      ],
      "destination": "wwwroot/lib/bootstrap/dist/js/"
    },
    {
      "library": "html5shiv@3.7.3",
      "files": [
        "html5shiv.js",
        "html5shiv.min.js"
      ],
      "destination": "wwwroot/lib/html5shiv/dist/js/"
    }
  ]
}

This should empty the jquery, jquery-validate and jquery-validation-unobtrusive folders in lib except for LICENSE.txt files. Delete these folders.

Edit _Layout.cshtml > include="Development" environment tag, delete the commented script tags:
<environment include="Development">
    @*<script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>*@
    <script src="~/lib/bootstrap/dist/js/bootstrap-native-v4.js"></script>
</environment>
Edit _Layout.cshtml > exclude="Development" environment tag, remove jquery.min.js and bootstrap.bundle.min.js CDN script tags and add bootstrap-native-v4.min.js:
<environment exclude="Development">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap.native/2.0.25/bootstrap-native-v4.min.js"
        asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap-native-v4.min.js"
        asp-fallback-test="window.BSN"
        integrity="sha256-RD3nVy1D0S4xfj5DyNqAHYDt+mBIW9E+DGacFg7961c="
        crossorigin="anonymous">
    </script>
</environment>

Search the project for "_ValidationScriptsPartial" and remove the partial tag where found. If you added the range validator method for checkboxes in Register.cshtml, delete it. Delete _ValidationScriptsPartial.cshtml from Identity > Pages and Pages > Shared.

Bootstrap v5 will not be dependent on jQuery. See Bootstrap 5 expected to completely replace jQuery and v5 without jQuery #23586. Consider Bootstrap Native a head start. I have created a project package which includes the Bootstrap Native library without jQuery. The ASP.NET Core 2.2 - Bootstrap Native Project will implement the features from most of my articles to date and become the base project for future articles.



1 Following


Comment Count = 0

Please log in to comment or follow.

Login Register