Something about the way that Spring Boot loads a web page is screwing things up with Onsen UI. The ons-navigator
and ons-splitter
tags do not work correctly when the pages are served from a Spring Boot application. The ons-navigator
tag is supposed to act as a placeholder for navigation through other HTML fragments. When served from Spring Boot, the tag does not load the appropriate page indicated in the tag attribute <ons-navigator page="foo.html"></ons-navigator>
. The <ons-splitter>
tag should show a side menu (and normally does without Spring Boot involved). Instead, tapping the menu icon simply dims the page a bit but does not show the menu as it normally does. I'm not sure what Spring Boot has broken in the normal operation of this web page. I will post as much relevant code as possible. This web page does work properly when loaded from a normal web server. But it doesn't work when loaded from Spring Boot; it displays a blank page. If I uncomment the Thymeleaf template tag below which loads the home.html
file, the page does load, but this is not the desired behavior, and in addition, the sidemenu still does not load properly.
Could it be one of the starters? I've tried so far placing the static pages under resources/static
directory. Regardless of how the CSS and JS is included it seems to result in the same behavior.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.moonlightcheese</groupId>
<artifactId>jobs</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jobs</name>
<description>Time tracking for billable hours</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
index.html
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8">
<!--
<link rel="stylesheet" href="https://unpkg.com/onsenui/css/onsenui.css">
<link rel="stylesheet" href="https://unpkg.com/onsenui/css/onsen-css-components.min.css">
<script src="https://unpkg.com/onsenui/js/onsenui.min.js"></script>
-->
<link rel="stylesheet" th:href="@{/onsenui/css/onsenui.css}"/>
<link rel="stylesheet" th:href="@{/onsenui/css/onsen-css-components.min.css}"/>
<script th:src="@{/onsenui/js/onsenui.min.js}"></script>
<!--
<link rel="stylesheet" href="onsenui/css/onsenui.css">
<link rel="stylesheet" href="onsenui/css/onsen-css-components.min.css">
<script src="onsenui/js/onsenui.min.js"></script>
-->
<script>
window.fn = {};
window.fn.toggleMenu = function () {
document.getElementById('splitter').right.toggle();
//document.querySelector('#menu').open();
};
// window.fn.loadView = function (index) {
// document.getElementById('appTabbar').setActiveTab(index);
// document.getElementById('sidemenu').close();
// };
window.fn.loadLink = function (url) {
window.open(url, '_blank');
};
window.fn.pushPage = function (page, anim) {
if (anim) {
document.getElementById('navigator').pushPage(page.id, {data: {title: page.title}, animation: anim});
} else {
document.getElementById('navigator').pushPage(page.id, {data: {title: page.title}});
}
document.getElementById('sidemenu').close();
};
window.fn.popPage = function (page, anim) {
if (anim) {
document.getElementById('navigator').popPage({data: {title: page.title}, animation: anim});
} else {
document.getElementById('navigator').popPage({data: {title: page.title}});
}
document.getElementById('sidemenu').close();
}
window.fn.resetToPage = function (page) {
const navigator = document.querySelector('#navigator');
navigator.resetToPage(page.name);
document.getElementById('sidemenu').close();
}
var $_GET = {};
if(document.location.toString().indexOf('?') !== -1) {
var query = document.location
.toString()
// get the query string
.replace(/^.*?\?/, '')
// and remove any existing hash string (thanks, @vrijdenker)
.replace(/#.*$/, '')
.split('&');
for(var i=0, l=query.length; i<l; i++) {
var aux = decodeURIComponent(query[i]).split('=');
$_GET[aux[0]] = aux[1];
}
}
</script>
<title>Jobs</title>
</head>
<body>
<ons-page>
<ons-splitter id="splitter">
<!-- The side menu -->
<ons-splitter-side id="sidemenu" page="sidemenu.html" swipeable side="right" collapse width="260px"></ons-splitter-side>
<!-- Everything not in the side menu -->
<ons-splitter-content>
<!-- this is how the navigator should be used -->
<ons-navigator id="navigator" page="home.html">
<!-- <ons-page> should be included here, but does not appear when requested from Spring Boot -->
</ons-navigator>
<!-- works but not desired behavior -->
<div th:replace="home.html"></div>
</ons-splitter-content>
</ons-splitter>
</ons-page>
<!--
<ons-toolbar>
<div class="center">Home</div>
<div class="right">
<ons-toolbar-button onclick="fn.toggleMenu()">
<ons-icon icon="ion-navicon, material:fa-bars"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
<ons-navigator id="appNavigator" swipeable swipe-target-width="80px" page="home.html">
<ons-page>
<ons-splitter id="appSplitter">
<ons-splitter-side id="sidemenu" page="sidemenu.html" swipeable side="right" collapse="portrait" width="260px"></ons-splitter-side>
<ons-splitter-content page="tabbar.html"></ons-splitter-content>
</ons-splitter>
</ons-page>
</ons-navigator>
-->
<style>
ons-splitter-side[animation=overlay] {
border-left: 1px solid #bbb;
}
</style>
<script>
// if("page" in $_GET) {
// document.getElementById("navigator").setAttribute("page", $_GET["page"] + ".html");
// } else {
// document.getElementById("navigator").setAttribute("page", "home.html");
// }
</script>
</body>
</html>
home.html
<ons-page>
<ons-toolbar>
<div class="center">Home</div>
<div class="right">
<ons-toolbar-button onclick="fn.toggleMenu()">
<ons-icon icon="fa-bars"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
"CONTENT NOT RELEVANT"
</ons-page>
HomeController.java (a simple Controller which just loads the home.html page if the template code is uncommented):
@Controller
@RequestMapping("/")
public class HomeController {
@GetMapping("/")
public String showHome(Model model) {
model.addAttribute("page", "home.html");
return "index";
}
}