Thymeleaf layout with multiple contents - layout

I'm new on Thymeleaf template engine, and I'm making an application with Spring Boot and Spring MVC. I'm working just with application.properties for the configuration.
I want to know how I can write only ONE layout but the contents in many files: for example content1.html, content2.html, etc. and use the layout that already have the header, the footer.
If it is possible, how can I send from the controller the content file that will be replaced in the layout?

You could do something like this. Let's say you create a page where all other content will be embedded - main.html. It will look something like this:
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3" xmlns="http://www.w3.org/1999/xhtml">
<div th:fragment="mainPage(page, fragment)">
<h4>Some header</h4>
<div th:include="${page} :: ${fragment}"></div>
<h4>Some footer</h4>
</div>
</html>
Then you want to create some page which will be embedded in your main.html page - some-page.html:
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3" xmlns="http://www.w3.org/1999/xhtml">
<div th:fragment="somePage">
<h1>${title}</h1>
</div>
</html>
The goal is to replace <div th:include="${page} :: ${fragment}"></div> within main.html with the content from some-page.html. In controller, that will look like this:
#Controller
public class DemoController {
#RequestMapping
public String somePage(Model model) {
// Note that you can easy pass parameters to your "somePage" fragment
model.addAttribute("title", "Woa this works!");
return "main :: mainPage(page='some-page', fragment='somePage')";
}
}
And there you go! Every time when you want to swap content in main.html, you just change page and fragment parameters within string in your controller.

Related

Embedding twitter timeline does not render in angular 7

I am following https://help.twitter.com/en/using-twitter/embed-twitter-feed for embedding timeline in the angular page. Only button renders but not the actual timeline.
The index.html looks like:
<body style="margin:0">
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<app-root></app-root>
</body>
app.component.html looks like below:
<a class="twitter-timeline"
href="https://twitter.com/TwitterDev/lists/national-parks?ref_src=twsrc%5Etfw">
A Twitter List by TwitterDev
</a>
Also tried things like app.component.ts:
ngOnInit(){
if ((<any>window).twttr.ready())
(<any>window).twttr.widgets.load();
}
But no luck
you need to load widgets.js script after twitter-timeline element is been render so if you place the script in index.html it is will load and the element hasn't render yet.
๐ŸŒŸ the best way around it is to create a script tag dynamically after the element is rendered.
twitter component
export class TwitterComponent {
#Input() user:string;
constructor(private renderer2: Renderer2,private el: ElementRef) {}
ngAfterViewInit() {
let scriptEl = document.createElement('script');
scriptEl.src = "https://platform.twitter.com/widgets.js"
this.renderer2.appendChild(this.el.nativeElement, scriptEl);
}
}
template
<a class="twitter-timeline" href="https://twitter.com/{{user}}">Tweets by {{user}}</a>
app componenet template
<app-twitter [user]="name"></app-twitter>
angular twitter widgets โšกโšก
ngAfterViewInit() a lifecycle hook that is called after Angular has fully initialized a component's view.
Updated ๐Ÿ”ฅ๐Ÿ”ฅ
a simple soulution mention in this answer before by user named Bernardo Baumblatt
put the script link in the index.html
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8">
</script>
load the twitter widgets when ngAfterViewInit method call
ngAfterViewInit() {
// #ts-ignore
twttr.widgets.load();
}
in any case the script has not loaded yet you will got an error like ๐Ÿ†˜ twttr is not defined ๐Ÿ‘‰ so download the widgets.js script and include it to your project by using import
main.ts
import './app/widgets.js'
demo ๐Ÿ’ฅ๐Ÿ’ฅ
I had a requirement of dynamically rendering timelines based on different twitter timelines.
I found a workaround by creating a variable in the constructor that stores the href based on the twitter username .
So for example if your link is "https://twitter.com/TwitterDev/lists/national-parks?ref_src=twsrc%5Etfw"
, you just put this in the constructor in a previously defined global variable , say "embedLink"
such as in your ts component:
#Component({
selector: 'app-tree-dashboard',
templateUrl: './tree-dashboard.component.html',
styleUrls: ['./tree-dashboard.component.css']
})
export class TreeDashboardComponent implements OnInit,AfterViewInit {
embedLink='';
constructor(private matIconRegistry: MatIconRegistry,
) {
this.embedLink= "https://twitter.com/TwitterDev/lists/national-parksref_src=twsrc%5Etfw"
}};
and then in your HTML :
<a class="twitter-timeline" href={{embedLink}}></a>
And lastly you only need to add the script in index.html which you have done already.
So you're good to go!
Below is my code. I'm creating blank website so I think it's should not be a problem. What I think is maybe the order of the script in index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Twitter</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></app-root>
</body>
<script
async
src="https://platform.twitter.com/widgets.js"
charset="utf-8"
></script>
</html>
In my app.component.html
<a class="twitter-timeline"
href="https://twitter.com/TwitterDev/lists/national-parks?ref_src=twsrc%5Etfw">
A Twitter List by TwitterDev
</a>
You can view my code here

Conditional class in Marko JS Template

I am using the layout taglib to extend a page to its template but i don't know how to pass a variable to the main layout and apply a conditional class.
Considering this is my main-layout.marko
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body class="#### (TITLE === 'REGISTER')?'ACTIVE':'INACTIVE' ####">
<layout-placeholder name="title"/>
<layout-placeholder name="body"/>
</body>
</html>
this is my registration.marko
<layout-use template="./layout.marko">
<layout-put into="title">
$data.title
</layout-put>
<layout-put into="body">
some content
</layout-put>
</layout-use>
and finally this is the code I use to render the page and pass the title data
router.get('/register', function(req, res, next) {
registration.render({
title: 'register'
}, res);
});
How can I create a conditional class on the main-layout.marko file that switches between active or inactive depending on the page title?
Thanks
You can pass data to a layout by adding additional attributes to your <layout-use> tag. See: marko-layout ยป Layout Data
For your example, the following will work:
In main-layout.marko:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body class="#### ${data.title === 'REGISTER' ? 'ACTIVE' : 'INACTIVE' } ####">
<layout-placeholder name="title">
${data.title}
</layout-placeholder>
<layout-placeholder name="body"/>
</body>
</html>
In registration.marko:
<layout-use template="./layout.marko" title="${data.title}">
<layout-put into="body">
some content
</layout-put>
</layout-use>
That should solve your problem, but let me know if you are still stuck.
there is another way of passing data t all of its template that is using $global in which you are passing your data .
and after using global you dont need to add attribute to any tag . you can access it by using like
out.global.username

How to change something dynamically in the main handlebars skeleton?

I am using handelbars as my templating engine and I am curious to whether I could edit the main handlebars file. What I can do at the moment is something like this:
main.handlebars:
<html>
<head>
</head>
<body>
<div id='headerBox></div>
<div id='contents'>{{{body}}}</div><!--all contents goes here-->
</body>
When I use this method I will could create templates e.g. home.handlebars etc.
But what If I wanted to change something dynamically in the main.handlebars? For example in my website, I would love to have a login form so I would like to have something like this in the main.handelbars:
<html>
<head>
</head>
<body>
<div id='headerBox>{{If logged in print name, if not print sign up}}</div>
<div id='contents'>{{{body}}}</div><!--all contents goes here-->
</body>
</html>
TLDR, how to I change something dynamically in the main handlebars skeleton.
Thanks!
You'll want to write a Handlebars Helper function. Since you didn't include anything about how you're verifying login, I'll write a little demo.
In your template file:
<div id='headerBox'>{{header}}</div>
Handlerbars.registerHelper('header', function() {
if (loggedIn) {
return //however you're getting a username
} else {
return Sign Up
}
});

Wicket: How to create a re-usable footer component section?

How do I create a component (like a footer section) and include it on a page?
I read stuff like markup inheritance, but that doesnt sound right (how would you re-use a footer section component in different pages when it can only inherit from a single page).
This is my 2nd day of using Wicket and wicket-library.com has some great examples, but at the moment it seems to be down when you try to view the source.
Thank you.
Create a basepage with header, footer, menu etc. Then extend you pages from that page. Use it like this:
public class BasePage extends WebPage {
public BasePage() {
add(new HeaderPanel("header"),
new FooterPanel("footer"),
new MenuPanel ("menu" ));
}
}
With this html:
<html xmlns:wicket>
<body>
<div wicket:id="header">
<div wicket:id="menu">
<wicket:child></wicket:child>
<div wicket:id="footer">
</body>
</html>
You would need to create a HeaderPanel, FooterPanel and MenuPanel.
Your child page example:
public class MyPage extends BasePage { ...}
Which has this html:
<html xmlns:wicket>
<body>
<wicket:extend>
</wicket:extend>
</body>
</html>
You can also create a no-menu basepage etc. The components and html you add to your child page will be placed between the tags of the basepage.

using this when including in php

in for example magento they have php seperated from phtml.
I also do the same thing.
But I can't figure one thing out, and that is:
When I have this php script:
class aclass extends main{
public function redirect(){
require_once($this->frontend_folder . $this->admin_folder . "beheer/edit_account.phtml");
}
public function nav_menu(){
return "<nav>some nav menu things in here</nav>";
}
and the "view" phtml script:
<!doctype html>
<html>
<head>
</head>
<body>
<div id="wrap">
<?php
echo $this->nav_menu();
?>
</div>
</html>
"$this" doesn't work, but how can I get this working?
you need to instantiate the class in the view.
<!doctype html>
<html>
<head>
</head>
<body>
<div id="wrap">
<?php
$c = new aclass; // instantiate the class
echo $c->nav_menu(); // run the function from the class
$c = null; // null the variable, maybe help garbage collection...
?>
</div>
</html>
this is not an optimal way to use it, but I hope the idea is clear.
EDIT: This is a simple solution, depending on your archetecture, you can do many things. In simpliest form, you should consider instantiating your class at the top of the view, then you can reference it by the handle you assign it to throughout the view.

Resources