Is it possible to call a fragment from within a fragment thymeleaf? - thymeleaf

I have a fragment for the head tag, and from within this I would like to call another fragment for my styles and scripts.
templates/fragments/commonHead.html
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="commonHead(title)">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<div th:replace="~{fragments/styles :: styles}"></div>
<div th:replace="~{fragments/scripts :: scripts}"></div>
<title th:text="${title}"></title>
</head>
templates/fragments/styles.html
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="styles" th:remove="tag">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.9.1/font/bootstrap-icons.css">
<link type="text/css" th:href="#{/css/normalize.css}" rel="stylesheet"/>
<link type="text/css" th:href="#{/css/style.css}" rel="stylesheet"/>
</div>
templates/fragments/scripts.html
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="scripts" th:remove="tag">
<script src="https://cdn.jsdelivr.net/npm/axios#1.1.3/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/js/bootstrap.bundle.min.js"></script>
</div>
And this is how I am calling the common head fragment.
templates/schedule.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/commonHead :: commonHead('Schedule')}"></head>
<body>
----
But when I do this, there are no errors, but the generated html does not complete the head tag. There must be some issue, but I have no indication what is wrong. Is it not possible to do this? I have tried both with <div th:replace="~{fragments/styles :: styles}"></div> and <div th:replace="~{styles :: styles}"></div> (same for scripts) in case it doesn't need the directory when the fragment is in the same folder.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<body>
EDIT:
After further troubleshooting here, it seems like it is completely overlooking the fragments in commonHead. If I intentionally call something with the wrong name (like <div th:replace="~{fragmentsX/stylesX :: stylesX}"></div>) I get no errors, and of course the fragment is not included.

It seems like the issue was with having the head tag in my commonHead fragment. When I changed that to div (with th:remove="tag" so that the div didn't show up in the html), then it worked fine.
Only change was made to templates/fragments/commonHead.html, final version is below.
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="commonHead(title)" th:remove="tag">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<div th:replace="~{fragments/styles :: styles}"></div>
<div th:replace="~{fragments/scripts :: scripts}"></div>
<title th:text="${title}"></title>
</div>

Related

Why open graph tags <meta> don't work on thymeleaf template

I added open graph meta tags to my thymeleaf page.
When I try to share my page - it looks like tags absent.
My page (partially) code
<!DOCTYPE html>
<html lang="ru" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
prefix="og: //ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link th:href="#{/css/app.css}" rel="stylesheet"/>
<title th:text="${'pageTitle'}">Title</title>
<meta property="og:type" content="article" />
<meta property="og:url" th:content="${'https://my_site_url'}" />
<meta property="og:title" th:content="${'pageTitle'}" />
<meta property="og:description" th:content="${'DESCRIPTION'}" />
<meta property="og:image" th:content="#{'https://pp.vk.me/c629531/v629531034/3172e/xEBYyER1WE4.jpg'}" />
</head>
<body>
<section class="base fullpage">
<div class="fullpage__content">
<div th:replace="component/partial/header"/>
<div th:replace="${page}"/>
</div>
<div class="fullpage__bottom">
<div th:replace="component/partial/footer"/>
</div>
</section>
<div th:replace="component/auth/auth"/>
</body>
</html>
And my share page button
<a th:href="#{'https://twitter.com/share?url=' + ${full_my_Page_Url}}" rel="canonical" target="_blank" class="c-article-socials__link twitter-share-button">
<div class="icon">
<img th:src="#{/img/icons/social/tw-h.svg}" alt="">
</div>
</a>
I expected share preview card if full by open graph tags, but now it is empty, I can share, but haven't information. Only the link from the share button, but no info from og prefix info
UPDATES
My generated HTML head code looks like:
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/css/app.css" rel="stylesheet">
<title>Статья</title>
<meta property="og:type" content="website">
<meta property="og:url"content="https://localhost:8443/articles/instruction/2">
<meta property="og:title" content="Статья">
<meta property="og:description" content="DESCRIPTION">
<meta property="og:image" content="/cmsstatic/img/posts/image_5.png">
</head>

Redirect from mvc view to angular route - Angular 6

I have integrated my angular project with ASP.NET MVC. I want to redirect my MVC page to angular route on first load. I have following code in my Index.cshtml page
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Myapp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body class="skin-blue sidebar-mini wysihtml5-supported">
<app-root></app-root>
<script type="text/javascript" src="~/Scripts/client/runtime.js"></script>
<script type="text/javascript" src="~/Scripts/client/polyfills.js"></script>
<script type="text/javascript" src="~/Scripts/client/styles.js"></script>
<script type="text/javascript" src="~/Scripts/client/vendor.js"></script>
<script type="text/javascript" src="~/Scripts/client/main.js"></script>
</body>
</html>
I also have the index.html page configurations in angular index page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Myapp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root>
<div class="wrapper">
</div>
</app-root>
</body>
</html>
Now I need to redirect the page from here to angular route where login route is defined for angular.
{ path: 'login', component: LoginComponent },
You have everything needed for Angular to run from your cshtml file. No need for index.html file.
Try to add this to your route config.
{path:'', redirectTo:'login', pathMatch: 'full' }
Once you add this Angular should redirect to login route by default.

md-icon md-list-icon not showing in angular 2

I want to display an icon before the list for which i had used like.
Not sure if the below is supported for Angular2.
The below module 'MaterialModule' is not required i guess, cause after removing it is working for me.
If i import this module, i get: no exported 'MaterialModule'!
app.module.ts //Not required to import here
import {MaterialModule} from '#angular/material';
imports: [
MaterialModule
...
index.html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
test.component.html
<md-list-item routerLink="2" routerLinkActive="active">
<md-icon md-list-icon>face</md-icon> <!--Icon not displaying here!-->
<div fxFlex="10"></div>
<div *ngIf="sidenavWidth > 6" class="sidenav-item">
<a *ngFor="let cat of categories; let i = index" href="javascript:; " class="list-group-item " (click)="getProducts(cat._id,i)">{{cat.category_name}}</a>
</div>
</md-list-item>
my \src\index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Food4Smiles</title>
<base href="/">
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.2.2/web-animations.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icon‌​s" rel="stylesheet">
<link rel="stylesheet" href="https://bootswatch.com/flatly/bootstrap.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="assets/static/hmicon.png">
</head>
<body>
<app-root></app-root>
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</body>
</html>
UPDATED ANSWER:
index.html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
test.component.html
<md-list-item routerLink="2" routerLinkActive="active">
<md-icon md-list-icon>face</md-icon> <!--Icon not displaying here!-->
<div fxFlex="10"></div>
<div *ngIf="sidenavWidth > 6" class="sidenav-item">
<a *ngFor="let cat of categories; let i = index" href="javascript:; " class="list-group-item " (click)="getProducts(cat._id,i)">{{cat.category_name}}
</a>
</div>
</md-list-item>
\src\index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Food4Smiles</title>
<base href="/">
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.2.2/web-animations.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icon‌​s" rel="stylesheet">
<link rel="stylesheet" href="https://bootswatch.com/flatly/bootstrap.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="assets/static/hmicon.png">
</head>
<body>
<app-root></app-root>
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</body>
</html>

How do I eliminate duplicate code in a rails erb file

What do I do to eliminate the double code that's happening?
In about.html.erb I have the following code:
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App | <%= #title %></title>
</head>
<body>
<h1>Pages#about</h1>
<p>Find me in app/views/pages/about.html.erb</p>
</body>
</html>
In the browser at localhost:3000/pages/about
<!DOCTYPE html>
<html>
<head>
<title>SampleApp</title>
<link href="/stylesheets/application.css" media="all" rel="stylesheet" type="text/css" />
<script src="/javascripts/application.js" type="text/javascript"></script>
<meta content="authenticity_token" name="csrf-param" />
<meta content="ra/NXpqBo1ccudzQ2HGHoo3OrZB2bLX732MQl+EJHU4=" name="csrf-token" />
</head>
<body>
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App | About</title>
</head>
<body>
<h1>Pages#about</h1>
<p>Find me in app/views/pages/about.html.erb</p>
</body>
</html>
</body>
</html>
The duplicate is part of app/views/layouts/application.html.erb

using 3 layouts on same gsp page

this is edit of my question that was first how to apply 2 layouts in the same gsp page but now i got problem with 3 layouts :) :
I am fairly new to all that css and layout stuff and i'm using grails 2.0 version
i have the following moduls in my problem:
1. main.gsp layout which basically have a nice header with company logo for all pages.
2. mainTabPanle.gsp layouts which basically contain some main tabs all pages should have
3. reportTab.gsp layout which basically contain nice report tabs and short javascript code to manipulate chosen tab color that all reports gsp pages should have.
what i am trying to do is to use this reportTab layout in all the reports gsp pages.
so this is what i got so far:
main.gsp:
<!doctype html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="${resource(dir: 'css', file: 'main.css')}"type="text/css">
<g:layoutHead/>
<r:layoutResources />
</head>
<body style="height:100%">
<div>some nice header in here </div>
<g:layoutBody/>
<r:layoutResources />
</body>
</html>
mainTabPanle.gsp (also located in layout folder)
<g:applyLayout name="main">
<!doctype html>
<html>
<head>
<g:layoutHead/>
<r:layoutResources />
</head>
<body>
<div>some main tabs here </div>
<g:layoutBody/>
</body>
<script type="text/javascript">
//script to manipulate main tabs
</script>
<r:layoutResources />
</body>
</html>
</g:applyLayout>
reportTabPanel.gsp:
<g:applyLayout name="mainTabPanel">
<!doctype html>
<html>
<head>
<g:layoutHead/>
<r:layoutResources />
</head>
<body>
<div>some reports tab panel </div>
<g:layoutBody/>
</body>
<script type="text/javascript">
//some script to manipulate report tab item
</script>
<r:layoutResources />
</body>
</html>
</g:applyLayout>
and now im using in moneyreport.gsp header the following line:
<meta name="layout" content="reportTabPanel" />
what i want to see is the nice header and the maintabsPanel and the reportTabPanel but all i see is the body of moneyreport.gsp
the weird thing is that if i use this:
<meta name="layout" content="mainTabPanel" />
inside moneyreport.gsp i see mainTab and the body of moneyreport.gsp as expected.
what am i doing wrong? i cannot use 3 layout on the same page?
thanks for your help guys ...
You can apply 2 layouts on the same page. In order to apply a different layout in a layout file, you need to use the applyLayout tag. Your reportTab should be something like this:
<g:applyLayout name="main">
<!doctype html>
<head>
<g:layoutHead/>
<r:layoutResources />
</head>
<body>
<div> some nice tabs here </div>
<g:layoutBody/>
</body>
<script type="text/javascript">
few line script handling chosen tab color in here
</script>
<r:layoutResources />
</body>
</html>
</g:applyLayout>
The best way is using templates because you can use as many as you want. I have this main HTML where I want to include different templates, like a menu and a generic content page:
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>
<g:layoutTitle default="Loto Tasks"/>
</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<g:layoutHead/>
</head>
<!-- Including menu -->
<g:render template="/templates/menu" />
<!-- Including generic content page -->
<g:render template="/templates/genericcontent" />
<g:layoutBody/>
</body>
</html>
I have a package named templates inside a views package, and inside templates I have two files, _menu.gsp and _genericcontent.gsp. The _genericcontent.gsp file looks like the following simple code. I could see that this is a little confusing if I insert a <head> with imports to other files, but you can import in the main file and it works:
_genericcontent.gsp
<div id="mainSearchPanel" class="searchPanel">
×
Filter panel here
</div>
<div id="search-icon" class="animate__animated animate__heartBeat animate__infinite animate__slower">
<i class="fas fa-search fa-2x"></i>
</div>
first thanks for your reply Anuj !
it kind of work but in a wrong way cuz i was getting weird html source:
i was getting 2 headers and 2 body tags so basically grails just copy paste all the layout
together and that wasn't good html page even that the browser display it right!
i found what i needed and that is simply using templates!
for example i have file called "_mainHeader.gsp" which look like this:
<!-- this is my main header for all gsp pages -->
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>IntentIQ Management System</title>
<link rel="stylesheet" href="${resource(dir: 'css', file: 'main.css')}"type="text/css">
<link rel="shortcut icon" href="${resource(dir:'images/myImg',file:'favicon.ico')}" type="image/x-icon">
and from all pages i can use those lines like for example in page1.gsp:
<g:render template="/templates/mainHeader" />
</head>
<body>
<h1> this is page1 with header from mainHeader.gsp template </h1>
</body>
</html>
pay attention for who ever who read this to:
1.temmplate file name are with '_' character
2.the closing body tag in "page1.gsp" is closing the body tag started at "_mainHeader.gsp" file.
so basically this tempaltes stuff is kind of copy paste of parts of gsp pages and its working great!
thanks for your reply never the less!

Resources