Thymeleaf loads CSS but not Javascript - javascript

I have a Spring boot app with a Thymeleaf template, that is supposed to load a css file and a javascript file.
The CSS file loads, but the Javascript file doesnt, it does not even try to get it from the server. There is no HTTP request for the Javascript, but the requests for the CSS are visible.
Where is my mistake?
I already tried putting the link for the javascript in the header next to the css but that made no difference.
My folder structure is as follows:
resources
-- static
---- bootstrap
------ css
---- js
Here the HTML:
<html xmlns:th="https://thymeleaf.org" lang="en" style="height: 100%;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Website Title</title>
<link rel="stylesheet" type="text/css" th:href="#{/bootstrap/css/bootstrap_custom.css}" />
</head>
<body class="d-flex flex-column h-100">
<script th:href="#{/js/main.js}" type="text/javascript"></script>
</body>
</html>
There is no error message, the tag for the javascript is simply ignored.

Your script end tag is incomplete. It should be:
<script th:src="#{/js/main.js}" type="text/javascript"></script>

The tag should read
<script th:src[...]>
instead of
<script th:href[...]>

Related

Rendering a Vue app in Shadow DOM using Custom Element

So I have a full featured (Routing etc) Vue 3 app that I need to embed on random page somewhere, but I don't want to use an iframe for various reasons so I'm looking to achieve this using Shadow DOM and Custom Element.
The way I thought it would work:
✅ Build the Vue App
✅ Publish the dist folder
✅ Create a Custom Element
✅ Create Shadow DOM in the constructor
✅ Load dist/index.html
❌ Vue App renders in Shadow DOM
... except it doesn't. Everything technically works but the Vue app doesn't render at all.
What am I missing?
My attempt: https://stackblitz.com/edit/javascript-7trm5i?devtoolsheight=33&file=index.html
Edited to add:
Same result even if I deploy the app to a service like Vercel and use it as src.
This is not a right way to do it. You are using fetch to get the HTML page. The HTML page has following script and style tags:
<!DOCTYPE html>
<html lang="en" data-theme="bumblebee">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Cart</title>
<script type="module" crossorigin src="/assets/index.0f5a3d92.js"></script>
<link rel="modulepreload" href="/assets/vendor.ab0eb239.js">
<link rel="stylesheet" href="/assets/index.8fd7686d.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
Look at this script: <script type="module" crossorigin src="/assets/index.0f5a3d92.js">.
When this tag is added via innerHTML, the browser will try to find the index.0f5a3d92.js file using the domain from which you are serving the main page. It is not asking the domain from where you are getting this HTML. Ideally, it should be this:
https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/index.0f5a3d92.js
But it is making call to this:
https://stackblitz.com/assets/index.0f5a3d92.js
You will have to rewrite the src attribute before you add it to HTML.
On a side note, this is an anti-pattern on what you are trying to do. Web component is not a real substitute for iFrame. Plus, a page should have only one top level head tag. You are introducing multiple head and body tags here. Browser will silently handle it but it is still anti-pattern.
The right way to do this is to bundle your Vue application with custom element definition. Then upload this bundled script to some CDN. From there, add it as a script on the page and the element should render when browser encounters the custom element.
You can not have multiple html, body, head tags in single document, so the html parser ignores the html, head and body tags of the Vue app.
Before:
<!DOCTYPE html>
<html lang="en" data-theme="bumblebee">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Cart</title>
<script type="module" crossorigin src="https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/index.0f5a3d92.js"></script>
<link rel="modulepreload" href="https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/vendor.ab0eb239.js">
<link rel="stylesheet" href="https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/index.8fd7686d.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
After parsing:
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Cart</title>
<script type="module" crossorigin src="https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/index.0f5a3d92.js"></script>
<link rel="modulepreload" href="https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/vendor.ab0eb239.js">
<link rel="stylesheet" href="https://vue-cart-ayoc0w7nv-eozzy.vercel.app/assets/index.8fd7686d.css">
<div id="app"></div>
So ultimately the html structure changes from the original one which Vue Virtual DOM can not work with.
So I don't think you can use Shadow DOM like an iframe.

External JS not linking to HTML

I have a very simple directory structure with an index.html file and a main.js file at the same level and no other files/folders. But I'm unable to link this js file in my index.html.
I have posted the contents of both files below, and the expected behaviour is to have a simple alert pop-up.
Here is my HTML File:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/main.css" />
<script type="text/javascript" scr="main.js"></script>
<title>External JS Issue</title>
</head>
<body>
Some Content Here.
</body>
</html>
Here is my JS File:
alert("If you can read this, it worked!");
However, if I include this JS line of code and put it directly inside my index.html, it works fine.
Here are the screenshots:
index.html:
main.js:
Browser Screenshot with External JS(NOT Working):
index.html with inline JS:
Browser Screenshot with Inline JS(Working):
You have a typo, the attribute of the <script> tag should be src, not scr.

JQuery in Laravel imported but not working

I am playing around with Laravel last version, trying to import and use JS files on the front-end. I have them stored in my folder 'public/js/'.
I have this Blade template you can see below, pizza.blade.php. If you inspect the page source, you can clearly see the JS files are existing, since their links, which are regularly working, are "http://localhost:8000/storage/...".
Nevertheless, they are not working inside the document and, inspecting the network tab, I can see they are not imported.
The image, pizza.png, located in 'public/storage' is displaying correctly.
What am i doing wrong?
Also, is there a better practice to use JS files, such as mix or npm? Thanks in advance.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script>src="{{asset('/js/jquery-3.3.1.js')}}"</script>
<script>src="{{ asset('/js/test.js') }}"</script>
<title>Document</title>
</head>
<body>
<h1 class="ciao">PIZZA LOGO</h1>
<div>
<img src="http://localhost:8000/storage/pizza.png" alt="">
</div>
</body>
<script>
$(document).ready(function () {
$(".ciao").css('display', 'none');
});
</script>
</html>
You have this error
<script>src="{{asset('/js/jquery-3.3.1.js')}}"</script>
this is just script with single javascript variable and string inside. You need this:
<script src="{{asset('/js/jquery-3.3.1.js')}}"></script>
this is html script tag with src attribute.

angular ng-include not working

The is a part of my html where I am trying to include the another HTML file "content.html" but it is not working. Those addresses in the source are correct but still I am not able to make it happen.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Basic Page Needs
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<meta charset="utf-8">
<title>Your page title here :)</title>
<meta name="description" content="">
<meta name="author" content="">
<!-- Scripts
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
<script type="text/javascript" src="js\jquery-3.0.0.min.js"></script>
<script type="text/javascript" src="js/angular.min.js"></script>
</head>
<body>
<div ng-include src="'content.html'"></div>
</body>
</html>
and this is my content.html
<div class="container">
<h1>Heading!</h1>
</div>
You should add ng-app="" to your page html tag, so that angular will get kick off on the page. After that will start traversing the page & will collect all directive & it will compile them.
<html lang="en" ng-app="">
Instead of ng-include with src you could directly pass template value in ng-include attribute as well.
<div ng-include="'content.html'">
Demo Plunkr

How to include HTML fragments via JQuery

I'm trying to include a HTML fragment inside another HTML page like so (below), via JQuery, but nothing works. What could I be doing wrong?
The folder structure looks as follows:
---> Project_Root --> jquery --> jquery-migrate-1.2.1.min
--> index.html
--> parts --> header.html
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="jquery/jquery-migrate-1.2.1.min"></script>
<script>
$(function(){
$("#navbar").load("parts/header.html");
});
</script>
<title>Sample</title>
</head>
<body>
<div id="navbar"></div>
</body>
</html>
header.html:
<p> This is my include file </p>
The actual jQuery library is missing:
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="jq/jquery-migrate-1.2.1.min"></script>
Migrate plugin is used when you want to use some removed/deprecated methods of jQuery which is not in the latest jQuery library.

Categories

Resources