Not sure how to name this correctly.
Is there any way to write one main template and many fragments and inject required fragment based on URL user requests.
Let's say i have /customers/profile and /customers/projects. I want to write one main customer.html template file and one customer-includes.html file with 2 {{ define "profile" }} and {{ define "projects" }} fragments.
Then i want have 2 handlers to handle /customers/profile and /customers/projects and to execute customer.html template.
But, when user go to the URL /customers/profile i want to inject in main template {{ template "profile" . }} and if he goes to /customers/projects i want to inject {{ template "projects" . }}.
What is the best way to do this?
I assume i need to use some kind of {{ if / else }} there. As example below. But mby there is better way.
{{ if ( eq .Section "customer-profile") }} // Could be replaced with Page ID
{{ template "profile" . }}
{{ else }}
{{ template "projects" . }}
{{ end}}
You may use template blocks for this.
templates/customers-base.html:
<html>
<head>
<title>{{.title}}</title>
<link rel="stylesheet" type="text/css" href="static/styles.css">
<!-- You can include common scripts and stylesheets in the base template -->
</head>
<body>
{{block "BODY" .}}
{{end}}
</body>
</html>
templates/customers-projects.html:
{{define "BODY"}}
<h1>Your Projects</h1>
<p>Normal template goes here</p>
<p>{{.myvar}}<p>
{{end}}
You can copy this format for templates/customers-profile.html.
Your project code:
data := map[string]interface{}{
"title": "Base template example",
"myvar": "Variable example",
}
layoutCustomersBase := template.Must(template.ParseFiles("templates/customers-base.html"))
layoutCustomersProjects := template.Must(layoutCustomersBase.ParseFiles("templates/customers-projects.html"))
// Or layoutCustomersProfile, if you are parsing in the '/customers/profile' handler.
err := layoutError.Execute(w, data)
Notice that you can define the "title" variable when you execute the customers-projects template; it will be used in the base template.
Related
I am experimenting with the package http/template.
I have also already managed that e.g. the header, footer, navbar and so on were included in the base template:
{{ define "base" }}
<!DOCTYPE html>
<html lang="en">
<!-- Start Head -->
<head>
{{ template "head" }}
</head>
<!-- End Head -->
<!-- Start Body -->
<body>
{{ template "navbar" }}
{{ template "content" }}
{{ template "footer" }}
</body>
<!-- End Body -->
</html>
{{ end }}
404 page:
{{ define "content" }}
[...]
<h1 class="text-light text-right">404</h1>
<small>{{.CurrentURL}}</small>
[...]
{{ end }}
So here the variable CurrentURL should be replaced by the current URL.
However, this is only displayed empty ("") on the website:
<small></small>
But now I want to replace a variable, which is displayed on the web page only as "".
Go Code:
Parser:
func (parser *TemplateParser) ParseTemplate(name string) (tpl *template.Template, err error) {
root, err := template.New("root").Parse(rootTmpl)
// ...
return root.ParseFiles(files...)
}
Route:
func (ws *WebServer) Exec(name string, r *http.Request, w http.ResponseWriter, data map[string]interface{}) (err error) {
// ...
// add default data
data["CurrentURL"] = r.URL.RequestURI()
// ...
return tpl.Execute(w, data)
}
Even with an array, I can't use range etc:
type Test struct {
CurrentURL string
C []string
}
t := Test{
CurrentURL: "Current URL",
C: []string {"C1", "c2", "ccc4"},
}
tpl.Execute(w, t)
<ul>
{{range .C}}
<li>{{.}}</li>
{{end}}
</ul>
<!-- No <li></li> is created -->
What am I doing wrong?
You have to pass the context to the instantiated templates. Use
{{ template "content" .}}
to pass the data in . to the content template.
You're not passing any data to the child templates. Per the docs:
{{template "name"}}
The template with the specified name is executed with nil data.
{{template "name" pipeline}}
The template with the specified name is executed with dot set
to the value of the pipeline.
I am using Go gin gonic for my web app. How do I use the same template file multiple times in 1 page with different variables passed to the template.
segment.tmpl
{{ define "segment" }}
<div>{{ .Variable }}</div>
{{ end }}
layout.tmpl
<!DOCTYPE HTML>
<html>
<body>
{{ template "segment . }} #with a variable 1
{{ template "segment . }} #with different variable
{{ template "segment . }} #another same template with another
</body>
</html>
main.go
r.GET("/home/", func(c *gin.Context) {
tmpl := template.Must(template.ParseFiles("templates/layout.tmpl", "templates/product_add.tmpl", "templates/segment.tmpl")
r.SetHTMLTemplate(tmpl)
c.HTML(200, "layout", gin.H {
"Variable1": "var1",
"variable2": "var2",
})
}
How do I use segment.tmpl multiple times in the page "home" and passing different kind of variables to the segment.tmpl?
I have searched everywhere and have found nothing, the closest thing is template.Clone, but still couldn't find any examples of it.
You can pass any value as the "pipeline" to the template, it doesn't have to be the "dot", i.e. you could pass the result of a function call, or, in this case, the result of accessing a map's value.
{{ template "segment" .Variable1 }}
and then inside the template "segment" you can refer to the pipeline using the dot, i.e. {{ . }}.
segment.tmpl
{{ define "segment" }}
<div>{{ . }}</div>
{{ end }}
layout.tmpl
<!DOCTYPE HTML>
<html>
<body>
{{ template "segment .Variable1 }}
{{ template "segment .Variable2 }}
{{ template "segment .AnotherVariable }}
</body>
</html>
any ideas why my configuration is exporting njk code instead of content?
<body class="font-sans" id="top" itemscope itemtype="http://schema.org/WebPage">
{{ content | safe }}
<script src="scripts/index.js"></script>
{ % include 'footer.njk' % }
</body>
You've got too many spaces in there.
Change
{ % include 'footer.njk' % }
to
{% include 'footer.njk' %}
I have two web page on golang and I want to embed this pages codes to {{.content}} variable (defined in templates/main.html) being with dynamic according to the coming requests.
For example if the guest enter the userregister page I want to the {{.content}} variable will be userregister codes otherwise userprofile codes.
templates/userregister.html page codes;
{{ define "userregister" }}
...
{{.specialmessage}}
...
{{ end }}
templates/userprofile.html page codes;
{{ define "userprofile" }}
...
{{.specialmessage}}
...
{{ end }}
templates/main.html;
{{ define "main" }}
<!DOCTYPE html>
<html lang="tr">
{{ template "head" . }}
<body>
<div class="container-fluid">
{{ template "header" . }}
<div class="row">
<nav class="col-12 col-md-2 p-0">
{{ template "leftmenu" . }}
</nav>
<div class="container-fluid col-12 col-md-10">
{{.content}}
</div>
</div>
{{ template "footer" . }}
</div>
</body>
</html>
{{ end }}
The userregister page controller;
func PgUserRegister(c *gin.Context) {
c.HTML(http.StatusOK,"main", gin.H{
"pgETitle": "User Register page",
"specialmessage": "You are on the userregister page.",
"content": template.ParseFiles("userregister.html"),
})
}
The userprofile page controller;
func PgUserProfile(c *gin.Context) {
c.HTML(http.StatusOK,"main", gin.H{
"pgETitle": "User Profile",
"specialmessage": "You are on the userprofile page.",
"content": template.ParseFiles("userprofile.html"),
})
}
Parse all templates when starting the router.
router.LoadHTMLFiles("templates/main.html", "templates/userregister.html", "templates/userprofile.html")
Then in your handler add to the gin.H{ ... } expression a boolean variable, e.g. "isLoggedIn", and then in your main template use an if-else action together with the template action.
{{ if .isLoggedIn }}
{{ template "userprofile" . }}
{{ else }}
{{ template "userregister" . }}
{{ end }}
I'm having an issue in Laravel 4.2 with the Form facade when using input names that represent multidimensional arrays. The form will load, display, and post data correctly unless there are values set in Input::old() (because of failed validation, etc.).
Here is a simple example that shows the problem:
routes.php:
Route::get('input-test', function() {
return View::make('input_test.index');
});
Route::post('input-test', function() {
return Redirect::back()->withInput(Input::all());
});
input_test/index.blade.php:
<!doctype html>
<html>
<head>
<title>Input Array Test</title>
</head>
<body>
{{ Form::open(array('url' => 'input-test')) }}
{{ Form::label('customer[some_customer_field][]', 'Customer Field:') }} <br>
{{ Form::text('customer[some_customer_field][]', null) }}
{{ Form::submit('Submit') }}
{{ Form::close() }}
</body>
</html>
Submitting this form will throw an error:
htmlentities() expects parameter 1 to be string, array given
Is there a way to get inputs with these types of names to work on postback?
That way is not the proper one.
Following one is it
{{ Form::label('customer[0][field_1], 'Customer Field:') }} <br>
{{ Form::text('customer[0][field_2]', null) }}
After that, if you want to duplicate it, you must use
{{ Form::label('customer[1][field_1], 'Customer Field:') }} <br>
{{ Form::text('customer[1][field_2]', null) }}
But if you want just get a simple array, you must use
{{ Form::label('customer[field_1], 'Customer Field:') }} <br>
{{ Form::text('customer[field_2]', null) }}