The use of if statements inside templates really is puzzling me.
I'm trying to put a class = "active" inside a nav list made with golang templates, to do a basic tab menu that detects the active tab.
Here's my attempt :
{{define "header"}}
<!DOCTYPE html>
<html>
<head>
<title>Geoprod</title>
{{template "stylesheet" .}}
</head>
<body>
<nav class="navbar" role="navigation">
<div class="navbar-header">
<a{{if eq .Active "accueil"}} class="active"{{end}} href="/">Geoprod</a>
</div>
<div class="navbar-body">
<ul class="navbar-list">
<li{{if eq .Active "societe"}} class="active"{{end}}>Société</li>
<li{{if eq .Active "dossier"}} class="active"{{end}}>Dossier</li>
<li{{if eq .Active "temps"}} class="active"{{end}}>Temps</li>
<li{{if eq .Active "mails"}} class="active"{{end}}>Mails</li>
</ul>
</div>
</nav>
{{end}}
And in main.go :
var FuncMap = template.FuncMap{
"eq": func(a, b interface{}) bool {
return a == b
},
}
var templates = template.Must(template.ParseGlob("templates/*.html"))
and in func main()
templates.Funcs(FuncMap)
The program compiles, but i've found out adding the {{if eq .Active "something"}} class="active"{{end}} (^^ which I included here) causes the program to not display any text anymore. Any idea why?
I tried to convert your code into a minimal working example, and I believe your code and template works as expected. You can see my code (and run it) on the Go Playground.
My guess about what went wrong: Did you notice that {{define ...}} only defines a template for future use. You will still need to tell Go to actually use this template, either by using {{ template "header" }} or similar in a main template, or by using templates.ExecuteTemplate.
Related
I have a Django project contains multiple templates like this:
<body>
<div>
<ul>
<li>
<a href="#">
customers
</a>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2"></script>
<!-- place project specific Javascript in this file -->
<script src="{% static 'js/project.js' %}"></script>
<script>
{% include 'vue_dashboard.js' %}
</script>
</body>
the vue_dashboard.js file is the following
var app = new Vue({
el: '#vue_app',
delimiters: ["{(", ")}"],
data: function () {
return {
selected: 'group',
}
},
methods: {
change_selected: function (type) {
this.selected = type;
},
}
Now, I'm trying to use this vue method inside my <a> tag for example like this:
<a href="#" onclick="change_selected(type='customers')">
customers
</a>
then inside some other div obtain the value of the selected variable in the data section:
<div>
{{selected}}
</div>
I've also tried:
{% verbatim %}
{{ selected }}
{% endverbatim %}
and few other things, I know I'm using it wrong, but what's the right way to do so? I'm not even sure if my template can communicate with the vue file like this
Change
<a href="#" onclick="change_selected('customers')"> <!-- removed type= -->
customers
</a>
this should work with verbatim but you can also change delimiters in vue.js like following
delimiters: ["{(", ")}"],
which you did but didn't change {{ to {( so please change like this:
<div>
{( selected )} // <= change here
</div>
The first problem was like #ashwin said with the brackets, the other one was that the Vue app closing brackets were missing, also onclick doesn't work, I replaced it with #click, then everything was okay
Basically, Im trying to integrate Vue with Django. I have the following template:
<!DOCTYPE html>
<html>
<head>
<title>Django Vue</title>
</head>
<body>
{% verbatim %}
<div id="components-demo">
<button-counter></button-counter>
</div>
{% endverbatim %}
<!-- Vuejs -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- App -->
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">You clicked me {{ count }} times.</button>
`
});
// App definition
new Vue({ el: '#components-demo' });
</script>
</body>
</html>
Everything is very simple, CDNs are used, not webpack. The component shows up, but the count does not. In other words, the curly braces are not functioning properly within my template. Why is that? I have the verbatim tag up and running.
It looks like this:
Any help?
You didnt wrap the {{count}} with a {% verbatim %} tag, which means {{count}} is being interpreted by Django, not by Vue (you should be able to see that this is the case if you inspect the template that is being rendered).
This should work:
<!-- App -->
{% verbatim %}
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">You clicked me {{ count }} times.</button>
`
});
// App definition
new Vue({ el: '#components-demo' });
</script>
{% endverbatim %}
The {% verbatim %} tag you used is not really necessary, because the reason you want to use it (in this case) is because both Django and Vue use the same mustache {{}} syntax, which is causing the conflict. This means you should use {% verbatim %} only if there would otherwise be a conflict of syntax (for example, the mustache syntax).
I am having a problem controlling whitespace and still formatting html/template templates in a readable fashion. My templates look somthing like this:
layout.tmpl
{{define "layout"}}
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
{{ template "body" . }}
</body>
</html>
{{end}}
body.tmpl
{{define "body"}}
{{ range .items }}
{{.count}} items are made of {{.material}}
{{end}}
{{end}}
code
package main
import (
"os"
"text/template"
)
type View struct {
layout string
body string
}
type Smap map[string]string
func (self View) Render(data map[string]interface{}) {
layout := self.layout + ".tmpl"
body := self.body + ".tmpl"
tmpl := template.Must(template.New("layout").ParseFiles(layout, body))
tmpl.ExecuteTemplate(os.Stdout, "layout", data)
}
func main() {
view := View{ "layout", "body" }
view.Render(map[string]interface{}{
"title": "stock",
"items": []Smap{
Smap{
"count": "2",
"material": "angora",
},
Smap{
"count": "3",
"material": "wool",
},
},
})
}
But that produces (note: there is a line above the doctype):
<!DOCTYPE html>
<html>
<head>
<title>stock</title>
</head>
<body>
2 items are made of angora
3 items are made of wool
</body>
</html>
What I want is:
<!DOCTYPE html>
<html>
<head>
<title>stock</title>
</head>
<body>
2 items are made of angora
3 items are made of wool
</body>
</html>
In other template languages I can say things like
[[- value -]]
and the whitespace before and after the action are stripped, but I don't see anything like that in html/template. Does this really mean I have to make my templates unreadable like the following?
layout.tmpl
{{define "layout"}}<!DOCTYPE html>
<html>
<head>
<title>.title</title>
</head>
<body>
{{ template "body" . }} </body>
</html>
{{end}}
body.tmpl
{{define "body"}}{{ range .items }}{{.count}} items are made of {{.material}}
{{end}}{{end}}
You can use white space controller
{{range .foos -}} // eats trailing whitespace
<tr><td>do something</td></tr>
{{- end}} // eats leading whitespace (\n from previous line)
Whitespace in this case makes no difference in the rendered output at the user's browser, so controlling it makes little sense above perhaps aesthetics.
Put differently, one can have nicely formatted templates (which I would prefer) or partially nicely formatted HTML (no nested indents). Pick one or post process the HTML using any of the existing formatters.
Yes, whitespace and lines are translated literally. If you have a line with just a {{ define }} or anything else that does not produce output, you will have an empty line in the parsed file.
Ideally, because you are using template, you should not need to view or edit the parsed output. For reference, use JSP/JSF and see the ugly output it gives you. View the source of most pages online, they're also ugly.
Good luck!
I am working with Velocity templates, where I need to have multiple pages that needs to follow the same template style, say "about_me", "contact_us" and "home", all these pages will have same header, left menu and only thing different is content.
For example, HTML for all of them would be exactly the same except for one in < div id="page-content" >.
<html>
<head>
.. some common css and js
</head>
<body>
<div id="main-content">
<div id="header">
Main Menu Bar on top
</div>
<div id="left-menu">
Menus on the left
</div>
<div id="page-content">
I could be contact us, or home or about us.
</div>
</div>
</body>
</html>
One of the ways I have done is by having separate .vm file for header and side menu and importing them over on each of aboutus.vm, contactus.vm and home.vm, but with this i have lot of duplicate code. Is there a way to define everything as a template and just have "page-content", defined in my .vm files?
You could parse a velocity file in the middle of your page and define the template name as a variable. That way you could point to a different page-content.vm file for each
In the below example $contentTemplate could equal any of the following:
home/page-content.vm
about/page-content.vm
contact/page-content.vm
See below
<html>
<head>
.. some common css and js
</head>
<body>
<div id="main-content">
<div id="header">
Main Menu Bar on top
</div>
<div id="left-menu">
Menus on the left
</div>
<div id="page-content">
#parse($contentTemplate)
</div>
</div>
</body>
</html>
I am trying to learn Play 2.0 with scala but I dont think i quite understand how the template system for play 2.0 works. I have used play 1.2 before and i am sort of looking for an equivalent to the #{include 'views/blah.html' /}. I essentially want to create a navbar that is rendered on all the pages.
Essentially in main.scala.html i have
#(title: String)(navbar: Html)(content: Html)
<!DOCTYPE html>
<html>
<head>
<title>#title</title>
<link rel="stylesheet" media="screen" href="#routes.Assets.at("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="#routes.Assets.at("images/favicon.png")">
<script src="#routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>
<header>
This is my header
</header>
<section class="navbar">#navbar</section>
<section class="content">#content</section>
<footer>
This is my footer
</footer>
and in my index.scala.html:
#navbar = {
<h1>Index</h1>
<ul>
<li>
<a href=#routes.Application.tasks>Tasks</a>
</li>
</ul>
}
#main("Home")(navbar){
content
}
in task.scala.html:
#(tasks: List[Task], taskForm: Form[String])
#import helper._
#main("Home") {
<h1>Index</h1>
<ul>
<li>
<a href=#routes.Application.tasks>Tasks</a>
</li>
</ul>
} {
task code
}
Now to include this navbar it seems i have to repeat this in every page this way i would have to hard code this navbar into every page. Is there a way to do this without without writing the whole navbar in every page?
I have also tried creating a navbar.scala.html file that contains
<h1>Index</h1>
<ul>
<li>
<a href=#routes.Application.tasks>Tasks</a>
</li>
</ul>
and saving under views/ then importing that using #import views.navbar but then i get an error stating 'navbar is not a member of views'. I am writing this in Eclipse Java EE IDE indigo if that helps.
Dont import it but just call it:
#navbar()
To include any other views template into another views template,
you simple call it using: #views.html.[location].[location].[location]()
Where [location] is just a break down of it's path.
for example:
#views.html.users.interface()
Be sure to put the "()" ie the brackets at the end of the statement if it does not take any parameters. Without the "()" you will get an error message like this:
"BaseScalaTemplate(play.api.templates...)"
If your template has parameters, be sure to include them when you call it, like this:
#views.html.users.interface( "name" )