4

I am using gin templating and to render an HTML I use

c.Writer.Header().Set("username", "myname")
c.HTML(200, "myservices", gin.H{
    "title":    "Dashboard",
    "username": "myname" })

I want to pass a variable (username) so that I can access that in the js files attached to my template. I can access the username variable in template using {{.username}}. How can make it global so that I can also access it across all the js files as well. I tried setting it in header but I can access that only when the HTML is loaded. I won't be able to use it before the template is loaded.

icza
  • 389,944
  • 63
  • 907
  • 827
codec
  • 7,978
  • 26
  • 71
  • 127

1 Answers1

4

You can insert a Javascript code into the HTML page (e.g. in the <head> section) where you create Javascript variables, and initialize them with the parameters passed to the template execution.

See this example:

func main() {
    t := template.Must(template.New("").Parse(templ))
    m := map[string]interface{}{
        "title":    "Test page",
        "username": "bob",
        "counter":  12,
    }
    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const templ = `<html><head>
<script>
    var _title = {{.title}};
    var _username = {{.username}};
    var _counter = {{.counter}};
</script>
</head><body>
</body>
</html>`

This results in an HTML document (try it on the Go Playground):

<html><head>
<script>
    var _title = "Test page";
    var _username = "bob";
    var _counter =  12 ;
</script>
</head><body>
</body>
</html>

What this means is that other Javascript code in the page (either inlined or referenced, external) will see the variables _title, _username, _counter and use them as regular variables, and they are initialized with values we passed to Template.Execute().

Note that the html/template package performs contextual escaping. See that it inserted the result of {{.title}} in quotes because it is a string and that is how it should be written in Javascript code, but no quotes were added when inserting the result of {{.counter}}, because it is a value of type int.

Also note that you should use a unique naming strategy to avoid collision with existing variables or variables that may be used in other Javascript code. Usually a special prefix (or postfix) does it.

Also check out this related question: Referencing Go array in Javascript

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
  • Do we really need to use Template.Execute(). Can't we pass the variables the way I did using c.HTML? I can still access those variables as `{{.username}}`. Can't I just store them as global variables like you did? – codec Aug 26 '16 at 08:01
  • @love2code You don't need to use that, you can just pass them using `c.HTML()`. I used `Template.Execute()` so that it works on the Go Playground, because the `github.com/gin-gonic/gin` package cannot be imported there. The principle to create and initialize Javascript variables is what matters, there rest is just so that it can run on the Go Playground. – icza Aug 26 '16 at 08:04