How work template inheritance for Pug/Jade? - node.js

I have problem with template inheritance (more precisely with - block css ).
I have nested templates: template.pug -> index.pug -> contactContainer.pug
Every file has block css. And template.pug get all block css by index.pug and contactContainer.pug (it is right), but in html duplicate contactContainer.css:
<div id="leftColumn">
<link rel="stylesheet" href="/stylesheets/layouts/main/contactContainer.css">
<div id="contactContainer">
<div id="concatSubcontainer"></div>
</div>
</div>
I think problem by I use "include" instead "extends", but so i'm not sure because I have little experience for Pug.
Example my files:
template.pug (main template file)
doctype html
html
head
include ./head
block css
block js
body
div(id="page")
include ./header
block body
include ./footer
index.pug (body file)
extends layouts/main/template
block append css
link(rel="stylesheet" type="text/css" href="/stylesheets/index.css")
block body
div(id="mainContainer")
div(id="leftColumn")
include ./layouts/main/contactContainer
div(id="rightColumn")
include ./layouts/main/selfContainer
contactContainer.pug (template for leftColumn)
block append css
link(rel='stylesheet', href='/stylesheets/layouts/main/contactContainer.css')
div(id="contactContainer")
div(id="concatSubcontainer")

Related

Thymeleaf layout with multiple contents

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.

ejs include on click

I'm trying to create a dynamically included in an ejs page (using <%- include('partials/content') %>) on my node.js project.
Is there a way I can create a variable for the to-be-included page and change it on a button click?
Let's assume your partials/content file includes content like:
<h1>Lorem ipsum dolor sit amet</h1>
A file named partials/content2:
<h1>consectetur adipiscing elit<h1>
Your main template file would wrap the partials content by a <div> with the id result and include a script file where you select this <div> by using var $result = $('#result'); so you have it in a variable. Then you can register a click handler on your button. On click you request the wished template file and replace the content.
Main template:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
<div id="result">
<%- include partials/content.ejs %>
</div>
<button id="change">change</button>
<script>
var $result = $('#result');
$('#change').click(function() {
$result.load('/content2');
});
</script>
</body>
</html>
Then you need a controller on the backend like:
app.get('/content2', function (req, res) {
res.render('partials/content2');
});

Display paragraph in Jade template

I have started working on a sample NodeJS / Express web application ,
and I am using Jade template engine.
Below is the partial .jade code for one of the screens.
html
head
script(src='/js/bootstrap.min.js')
script(src='/angular/angular.min.js')
link(href='/css/bootstrap.css' , rel='stylesheet')
body
div(class='container')
p= error
My intention is to have "p" element within the div
<div class='container'>
<p>Error message comes here.. </p>
</div>
But what is happing is "p" element is after div
<div class='container'>
</div>
<p>Error message comes here.. </p>
Please let me know what needs to be modified so that "p" is within div.
Your code may be indented in the wrong way. Try this:
html
head
script(src='/js/bootstrap.min.js')
script(src='/angular/angular.min.js')
link(href='/css/bootstrap.css',rel='stylesheet')
body
.container
p=error
Copied the jade code and seems you indented unevenly. Try this :
html
head
script(src='/js/bootstrap.min.js')
script(src='/angular/angular.min.js')
link(href='/css/bootstrap.css' , rel='stylesheet')
body
.container
p error
This worked for me
div.container
p= error

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
}
});

Express & Jade - max Block Nesting

i use Express 3x + Jade + bootstrap +..etc
my block/extend structure looks like this
.layout.jade (only head stuff)
.topNav.jade (only top nav)
.sideNav.jade (sideNav and control center interface)
.slidePrem.jade (the actual content)
now i try to res render slidePrem
-> this renders sidenav, topnav, layout (so the "extends" statement is read out of slideprem)
but it wont show any content of slidePrem
so after many many hours of recoding, searching, reintending, etc
. i rewrote structure to slideprem -> sidenav -> layout
-> this renders slideprem, sidenav, layout
->>> So is there actually a limit of nested blocks?
-> is it editable?
-> or cld u imagine the error somewhere else?
regards Pika
Edit:
//slidePrem.jade//
extends ../sideNav
block wall
#bla (or alert or sth)
//sideNav.jade//
extends topNav
block content
#subHeader
#subHeadNav
#Content //doesnt conflict with "block content"
div.container
div.row
div.span9
block wall
div.span3
// further code
//topNav.jade//
extends layout
block navigation
div.topnav.....
div...
...
block content
#modal
//layout.jade//
doctype 5
html
head
title= title
<meta name="viewport" content="width=device-width, initial-scale=1.0">
link(rel='stylesheet', href='http://fonts.googleapis.com/css?family=Titillium+Web&subset=latin,latin-ext', type='text/css')
link(rel='stylesheet', href='/bootstrap/css/bootstrap.min.css')
link(rel='stylesheet', href='/bootstrap/css/bootstrap-responsive.min.css', media="screen")
link(rel='stylesheet', href='/stylesheets/style.css')
link(rel='stylesheet', href='/stylesheets/cCenter.css')
script(src='/javascripts/jq.js')
script(src='/bootstrap/js/bootstrap.min.js')
script(src='/javascripts/core.js')
script(src='/javascripts/ajax.js')
body
block navigation
You should try to work with includes instead of extends.
So you can try for your layout.jade :
html
head
(...)
body
block navigation
And in your navigation.jade block
extends layout
block navigation
.topnav (div aren't required in jade)
(...)
include content
Your content.jade only needs then
#subHeader
#subHeadNav
#Content //doesnt conflict with "block content"
div.container
div.row
div.span9
include wall
div.span3
If that's not clear enough, you can find all the include documentation on the GitHub page of the project.
I hope it'll help.

Resources