How to set web template variable to a dynamic html&golang code? - go

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

Related

Go Templates: Can't identify field <field> in type string (struct being passed to template treated as string?)

I have the following code for an image modal pop-out. Photos is a struct that's passed to the frontend from the server. An instance of Photos is passed to the following template:
...
{{ $info := .GenInfo true }}
<img src={{ $info.Url }} data-bs-toggle="modal" data-bs-target="#{{ $info.Id }}" />
{{ template "photo-modal" $info }}
{{ end }}
{{ $info = .GenInfo false }}
<img src={{ $info.Url }} data-bs-toggle="modal" data-bs-target="#{{ $info.Id }}" />
{{ template "photo-modal" $info }}
{{ end }}
...
Because Go only allows a single attribute to be passed to a template, I created the following function to pass the url and a generated id to the sub-template:
type Photos struct {
LeftUrl string
RightUrl string
Date string
}
type photoInfo struct {
Id string
Url string
}
func (p *Photo) GenInfo(isLeft bool) photoInfo {
var info photoInfo
if isLeft {
info.Url = p.LeftPhoto
} else {
info.Url = p.RightPhoto
}
reg, _ := regexp.Compile("[^a-zA-Z0-9 ]+")
info.Id = reg.ReplaceAllString(info.Url, "")
return info
}
Here is the modal template that I'm trying to make reusable elsewhere in the app:
{{ define "photo-modal" }}
<div class="modal fade" id={{ .Id }} tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-body">
<img src={{ .Url }} />
</div>
</div>
</div>
{{ end }}
The app compiles, but when I try and load the page, I get the following error:
template: photo-modal.html:2:30: executing "photo-modal$htmltemplate_stateHTMLCmt" at <.Id>: can't evaluate field Id in type string
and the page itself crashes.
I would appreciate any help on this, I'm not sure why. Maybe the struct is being treated as a string for some reason? If that's what's happening, how can I get the template to treat the struct as a struct?

Golang Gin Gonic c.HTML Access passed interface variables inside nested header/footer template

I have template header.html and home.html
data:= gin.H{
"title": "Home",
"firstname": "firstname",
"lastname": "lastname",
}
c.HTML(http.StatusOK, "home.html", data)
This is my home.html template
{{ template "header.html" }}
<!-- BEGIN: Content-->
<div class="app-content content ">
<div class="content-overlay"></div>
<div class="header-navbar-shadow"></div>
<div class="content-wrapper">
</div>
</div>
</div>
<!-- END: Content-->
{{ template "footer.html" }}
I am able to access all three variables(title, firstname, lastname) inside home.html with {{ .firstname }} but unable to access inside header.html or footer.html
This is how I am loading my static and templates
router.Static("/static", "./static")
router.LoadHTMLGlob("templates/**/*.html")
Please note my template is working fine as my header + home + footer content is loading and working properly except variables.

Use the same template with different param/variables in 1 page

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>

Hugo: How can I display an image in my post list

I am trying to display an image in my post list.
In order to achieve that I added some tags in my post.md:
---
title: "Hello"
header_image: /images/blog/2019/water.jpg
images: /images/blog/2019/water.jpg
resources:
src: /images/blog/2019/water.jpg
title: "The image I want"
---
Then I edited list.html and tried different things:
{{ define "main" }}
<div class="archive animated fadeInDown">
<ul class="list-with-title">
<div class="listing-title">{{.Title}}</div>
{{ range .Pages }}
<ul class="listing">
<div class="listing-item">
<div class="listing-post">{{ .Title }}
{{ with .Resources.ByType "image" }}
<div class="Image">
{{ range . }}
<img src="{{ .RelPermalink }}">
{{ end }}
</div>
{{ end }}
{{ $.Param "header_image" }}
-- {{ range .Page.Resources }}
THERE IS ONE ITEM => NOT WORKING
{{ end }} <<
<div class="post-time"><span class="date">{{.Date.Format "Jan 2" }}</span></div>
</div>
</div>
</ul>
{{ end }}
</div>
{{ end }}
But when I try to display Resources, I always get [] (nothing)
Any idea what I am doing wrong?
I don't think your {{ $.Param "header_image" }} is working, either.
The way to access your custom, non-standard variables on pages, as well as sites, is through the .Params object, e.g. .Params.header_image. Note the small letter at the beginning, as opposed to capital letters for built-in params.
Page-level params on the Hugo Docs
Custom page params
To access
---
header_image: /images/blog/2019/water.jpg
---
you can use this in your page template.
{{ .Params.header_image }}
Resources
Page resources on Hugo Docs
It seems that resources is actually an array of objects, and with yaml, you should actually have something like this (note the dash):
resources:
- src: /images/blog/2019/water.jpg
title: "The image I want"
Also mind that this feature seems to only be available only for page bundles
Debugging
You can use {{ printf "%#v" .Resources }} for debugging.

Hugo definition of non-site level variables/parameters query

I am using Hugo Universal Theme. I am new to static site generators. This question is for someone who is familiar with hugo templates.
In layouts/partials/features.html we can see where $element.name and $element.name.description are rendered:
{{ if isset .Site.Params "features" }}
{{ if .Site.Params.features.enable }}
{{ if gt (len .Site.Data.features) 0 }}
<section class="bar background-white">
<div class="container">
{{ range $index, $element := sort .Site.Data.features "weight" }}
{{ if eq (mod $index 3) 0 }}
<div class="col-md-12">
<div class="row">
{{ end }}
<div class="col-md-4">
<div class="box-simple">
<div class="icon">
<i class="{{ .icon }}"></i>
</div>
<h3>{{ $element.name }}</h3>
<p>{{ $element.description | markdownify }}</p>
</div>
</div>
{{ if or (eq (mod $index 3) 2) (eq $index (sub (len $.Site.Data.features) 1 )) }}
</div>
</div>
{{ end }}
{{ end }}
</div>
</section>
{{ end }}
{{ end }}
{{ end }}
The data to be rendered in this case are defined in data/features/consulting.yaml as follows:
weight: 4
name: "Consulting"
icon: "fa fa-lightbulb-o"
description: "Fifth abundantly made Give sixth hath..."
What should I do to add new variable to the yaml file that can later then be rendered through the html file when hugo is compiling the site. I tried to simply add another parameter param1 and then insert a corresponding line in the html file as <p>{{ $element.param1 | markdownify }}</p> just below description paragraph but got error
ERROR 2018/08/23 10:42:42 Error while rendering "home" in "":
template: index.html:22:11: executing "index.html" at <partial
"features.ht...>: error calling partial: template:
partials/features.html:18:56: executing "partials/features.html" at
: wrong number of args for markdownify: want 1 got 0
Clearly it seems I have not been able to define the variable properly, but where should I do that? I can add another site variable to config.toml, but I want to learn how to make page specific variables that can be defined in yaml/frontmatter type entries. I tried reading about hugo variables but got bogged down in what is a variable and what is a shortcode. Many thanks for your help with this example.
Well, I found a working answer, but I still do not fully understand how it fits with Hugo variable system, so a better answer and or comments are highly welcome.
It appears quite simple. I had to define url variable in the yaml file:
name: "History"
position: "Hx"
url: "/blog/2018/08/23/01-history/"
and then use in the html file like this:
{{ if .url }}
<a href="{{ .url }}">
<h5>{{ .name }}</h5>
</a>
{{ else }}
<h5>{{ .name }}</h5>
{{ end }}
What it does is puts the .name in link tag, if .url is defined in .yaml. This works also if an absolute URL is given. So it appears that a page variable is referred to as .myVariable. the template authors used $element.name in another place as above, which confused me.
I also can refer to the parameter defined in the frontmatter as .Params.name
I found pointers at https://github.com/devcows/hugo-universal-theme/pull/166 and tested in adjusting the template; it works well.

Resources