Search code examples
gogo-html-template

Template partially rendering as plaintext


I'm having trouble with one particular thing I'm trying to put through Go html templates.

(all will be condensed/simplified for brevity)

I have one base template:

<html>
    <head>
        <title>{{ .Title }}</title>
    </head>
    <body>
        {{ template .PageBody . }}
    </body>
</html>

And a device template:

{{ define "device" }}
<div class="nav">
    <div class="links">
        {{ .DeviceLinkList }}
    </div>
</div>
<div class="textData">
    <div class="deviceNick">
        {{ .Nickname }}
    </div>
</div>
{{ end }}

The way I set this up is like so:

In the main.go file:

package main
import "html/template" //among others, of course. 

var err error
var tmplInit *template.Template
type TemplVals struct{
    Title       string
    Version     string
    Release     string
    PageBody    string
}
var templVals TemplVals

func init(){
    // Prepare GOHTML templates
    tmplInit, err = template.ParseGlob("./html_templates/*.gohtml")
    if err != nil { log.Panic("Cant load templates! ", err) }
    templVals.Version = serverDetails["version"]
    templVals.Release = serverDetails["release"]
}

//Main only has MUX routing using Gorilla Mux

In the deviceController.go file:

type DeviceValues struct{
    DeviceLinkList string
    Nickname string
    Title string
}


func home(w http.ResponseWriter, r *http.Request){
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    var deviceData DeviceValues

    // Seems to not be loaded as HTML when passed to template?
    deviceData.DeviceLinkList = loadDeviceList("example") 

    deviceData.Nickname = loadDeviceData("example")
    deviceData.PageBody = "device"
    deviceData.Title = "Home"

    tmplErr := tmplInit.Execute(w, deviceData)
    if tmplErr != nil{ log.Panic(tmplErr) }
}

func loadDeviceList(user string)(string){
    var deviceid, linkList string
    linkList = `<ul>`
    for getIDs.Next(){
        err = getIDs.Scan(&deviceid) // SQL gathers this
        if err != nil { panic(err) }
        linkList = linkList + `<li><a href="#" onclick="loadDevice('`+deviceid+`')">`+deviceid+`</a></li>`
    }
    linkList = linkList + `</ul>`

    return linkList
}

func loadDeviceData(user string)(string){
    //SQL retrieves data for devices associated to passed in user
    //for brevity:
    return "Example Nickname"
}

The problem is the nickname is loaded properly, and there are other fields such as battery levels and sensor readings that all pass through properly and can even be used in JS functions, but the DeviceLinkList is rendered in regular string no matter what I do. It's not a list, just pukes out the HTML as-is in plain text.


Solution

  • The solution is so much simpler than I thought. I wasn't using the correct wording to find this SO answer, but it solves it perfectly: Go template.ExecuteTemplate include html

    The gist is I needed to make the DeviceLinkList type template.HTML instead of string, and when I assign it a value, it needs to be deviceData.DeviceLinkList = template.HTML("<ul><li>list1</li><li>list2</li></ul>")