Mastodon

Adding Bootstrap to an Angular Application that got generated with JHipster

Yesterday, I wanted to add a simple Bootstrap Navigation bar to my Angular application that I created with JHipster. Although this is a standard component, I had difficulties because I didn’t understand how Bootstrap, Angular and NodJS play together. This article explains how to “really” add Bootstrap to an Angular application that got created by JHipster.

Bootstrap comes with Angular. Kind of.

After generating a fresh project with JHipster, Bootstrap styling is already available:

Adding Bootstrap to an Angular App

This can be seen when using some Bootstrap styling in main.component.html:

<table class="table table-striped">
    <thead>
    <tr>
        <th scope="col">#</th>
        <th scope="col">First</th>
        <th scope="col">Last</th>
        <th scope="col">Handle</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <th scope="row">1</th>
        <td>Mark</td>
        <td>Otto</td>
        <td>@mdo</td>
    </tr>
    </tbody>
</table>

This table is styled correctly:

Correctly styled table about first, last and handle

After using those styles throughout my application, I thought that I could use all Bootstrap functionality. Adding a navigation bar was also fairly easy and looked OK:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
 
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
                <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    Dropdown
                </a>
                <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                    <a class="dropdown-item" href="#">Action</a>
                    <a class="dropdown-item" href="#">Another action</a>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item" href="#">Something else here</a>
                </div>
            </li>
            <li class="nav-item">
                <a class="nav-link disabled" href="#">Disabled</a>
            </li>
        </ul>
        <form class="form-inline my-2 my-lg-0">
            <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
        </form>
    </div>
</nav>

not working Burger Button 1 not working Burger Button 2

However, it didn’t work. When clicking either on the burger button (with a minimized browser window) or the dropdown button, nothing happened.

Only CSS Styling is Usable – Not Java Script

I learned that I had to manually add the NodeJS- and Bootstrap scripts to my index.html:

...
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>

It’s important to have the NodeJS scripts before the Bootstrap scripts.

After adding those lines, the burger button worked:

working burger button

Bootstrap vs Angular vs JQuery

In my search for this solution, I found a few articles that made me think about the web ecosystem. Seemingly, there are quite a few approaches to using Bootstrap with Angular.

According to this article, only UI Bootstrap should be used with Angular, under no circumstances should JQuery be added to Angular projects because JQuery “fights directly with how you use Angular to manipulate your views”. This article basically says that my approach is exactly plain wrong. I will have a look into this, but for this article it’s important to have a working solution and to document the reason why Bootstrap seems to be added in the Angular project but the scripted components don’t work.

Ng Bootstrap is a library especially designed to provide directives for Angular and kind of wrap the Bootstrap functionality.

The solution described in this article, adding the full Bootstrap library to Angular, is the way a fellow software craftsman solves the same issue in his own project.

Pace of the Web Ecosystem

I don’t have problems with ambiguousness in regard to solutions of software engineering problems. In the ecosystem of web frontends however, there seem to exist especially numerous solutions to a problem that don’t offer a unique selling point. I could implement every one of the three mentioned solutions and end up with a very similar result. As if the many possible solutions are making the situation not challenging enough, it’s very hard to find documentation because the libraries release new versions very often.

However, this is a topic for another article or – quite possible – not a topic at all because I’m only just beginning to (again) develop web applications and don’t understand the true meaning of the ecosystem.

TL;DR

When adding Bootstrap to an Angular application that got generated with JHipster, the script-files have to be manually added to the index.html because Angular only brings the Bootstrap styles, not the Java Script functionality.