3

I was exploring a little Spring Boot, and I was having a look at some frontend libraries - which I admit I have almost never seen :)

I am probably doing some stupid mistake that makes Bootstrap not working. I am trying to set up a header page. As I hate doing simple things, I am using Spring Boot, Webjars and Thymeleaf. All for the first time. But it seems everything is all right, and I cannot understand what is wrong.

First of all, here is the Gradle dependencies. I am using spring 2.0.0.M7. I cut the applied plugins repositories and group/version

buildscript { ext { springBootVersion = '2.0.0.M7' } repositories { mavenCentral() maven { url "https://repo.spring.io/snapshot" } maven { url "https://repo.spring.io/milestone" } } dependencies { classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: "${springBootVersion}" } } // ##### COMPILE DEPENDENCIES // DATABASE compile group: 'mysql', name: 'mysql-connector-java' // SPRING compile group: 'org.springframework.boot', name: 'spring-boot-devtools' compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa' compile group: 'org.springframework.boot', name: 'spring-boot-starter-json' compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' compile group: 'org.springframework.boot', name: 'spring-boot-starter-web' // THYMELEAF compile group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '2.2.2' // WEB JAVASCRIPT LIBS compile group: 'org.webjars', name: 'webjars-locator', version: '0.32-1' compile group: 'org.webjars', name: 'bootstrap', version: '4.0.0-beta.3' 

I am using webjars locator. I liked this approach because I have complete control of my libraries here, and I do not have to put version numbers on the application.

I have then set up the resource handler to retrieve the webjars, and the spring layout dialect...

@Bean WebMvcConfigurer configurer() { return new WebMvcConfigurer() { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/webjars/**") .addResourceLocations("/webjars/") .resourceChain(false); } }; } @Bean LayoutDialect layoutDialect() { return new LayoutDialect(); } 

... the Spring application...

@SpringBootApplication(scanBasePackages = { "it.aegidea.wolf" }) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 

... the controller...

@Controller public class HomepageController { @RequestMapping(value = "/", method = RequestMethod.GET) public String getHomepage() { return "homepage"; } } 

... the overall layout...

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <!--/* Each token will be replaced by their respective titles in the resulting page. */--> <title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Task List</title> <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css" /> </head> <body> <div th:include="commons/header :: page-header"></div> <div class="container"> <div layout:fragment="content"> </div> </div> <!-- Injected --> <script src="/webjars/jquery/jquery.min.js"></script> <script src="/webjars/popper.js/dist/umd/popper.js"></script> <script src="/webjars/bootstrap/js/bootstrap.min.js"></script> </body> 

... the header...

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <body> <nav class="navbar navbar-default navbar-fixed-top" th:fragment="page-header"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#title-collapse" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="title-collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <form class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> </body> </html> 

... and finally, the homepage.

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{commons/layout}"> <head> <meta charset="UTF-8" /> <title>Wolf</title> </head> <body> <div layout:fragment="content"> <p th:text="'Hello World!'" >Hello World!</p> <div class="btn-group"> <button type="button" class="btn btn-success">This is a success button</button> <button type="button" class="btn btn-warning">This is a warning button</button> <button type="button" class="btn btn-danger">This is a danger button</button> </div> </div> </body> </html> 

The (weird) effect is that style get correctly applied to the buttons in the homepage, but not to the navbar.

What I've tried to do is

  • trying to include bootstrap, popper and jquery with direct links (taken from Bootstrap homepage)
    • trying to directly include the header into the homepage, just after

I am 100% sure I am doing some incredibly stupid mistake, but I've probably seen the code so many times that I cannot see what I am doing wrong.

Thanks for anyone's help :)

Lorenzo

3
  • can you upload your full repo to github? Commented Jan 16, 2018 at 18:34
  • @chenrui thanks :) github.com/il-lore/tmp_wolf.git Commented Jan 22, 2018 at 17:00
  • just FYI, I started adding some hibernate user table and spring security stuff, so things might be slightly different from the code I've posted Commented Jan 22, 2018 at 17:04

1 Answer 1

1

As expected, the answer is always simpler than expected. I was using bootstrap 3 css classes (navbar-fixed-top) with bootstrap 4, which has changed the classes.

Example header for bootstrap 4:

<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> 

Example menu item:

<li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> 

Here is a guide for bootstrap 4

https://getbootstrap.com/docs/4.0/components/navbar/

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.