Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map Json Data To Html Template In GoLang

Tags:

json

html

go

I am looping through my API response and adding it to the html template like this,

 // Following sends same information as above to the browser as html
     t, err := template.New("TopMovies").Parse(`
      {{define "TopMovies"}}
        <html>
        <ul>
        {{$ImgUrl := "http://image.tmdb.org/t/p/w185" }}
        {{range $movies := .Results}}
        <li>{{$ImgUrl}}{{$movies.PosterPath}}</li>
        <li>{{$movies.Adult}}</li>
        <li>{{$movies.Overview}}</li>
        <li>{{$movies.ReleaseDate}}</li>
        <li>{{$movies.GenreIds}}</li>
        <li>{{$movies.Id}}</li>
        <li>{{$movies.OriginalTitle}}</li>
        <li>{{$movies.OriginalLanguage}}</li>
        <li>{{$movies.Title}}</li>
        <li>{{$ImgUrl}}{{$movies.BackdropPath}}</li>
        <li>{{$movies.Popularity}}</li>
        <li>{{$movies.VoteCount}}</li>
        <li>{{$movies.Video}}</li>
        <li>{{$movies.VoteAverage}}</li>
        {{end}}
        </ul>
        </html>
      {{end}}
      `)
    err = t.ExecuteTemplate(w, "T", p) // This writes the client response
}

I am under the impression I should be able to call this in my html templates like this,

{{.TopMovies}}

But when I run the app the data does not appear in the html page I am calling it in. What am I missing here?

I create a struct like this,

//A Page structure
type Page struct {
  Title string
  TopMovies string
}

Then I create my handle like this,

func TopMoviesHandler(w http.ResponseWriter, r *http.Request) {
   res, err := http.Get(url)
      if err != nil {
        panic(err)
      }
      defer res.Body.Close()

      body, err := ioutil.ReadAll(res.Body)
      if err != nil {
        panic(err)
      }
      var p Payload

      err = json.Unmarshal(body, &p)
      if err != nil {
        panic(err)
      }

  // Following sends same information as above to the browser as html
     t, err := template.New("TopMovies").Parse(`
      {{define "TopMovies"}}
        <html>
        <ul>
        {{$ImgUrl := "http://image.tmdb.org/t/p/w185" }}
        {{range $movies := .Results}}
        <li>{{$ImgUrl}}{{$movies.PosterPath}}</li>
        <li>{{$movies.Adult}}</li>
        <li>{{$movies.Overview}}</li>
        <li>{{$movies.ReleaseDate}}</li>
        <li>{{$movies.GenreIds}}</li>
        <li>{{$movies.Id}}</li>
        <li>{{$movies.OriginalTitle}}</li>
        <li>{{$movies.OriginalLanguage}}</li>
        <li>{{$movies.Title}}</li>
        <li>{{$ImgUrl}}{{$movies.BackdropPath}}</li>
        <li>{{$movies.Popularity}}</li>
        <li>{{$movies.VoteCount}}</li>
        <li>{{$movies.Video}}</li>
        <li>{{$movies.VoteAverage}}</li>
        {{end}}
        </ul>
        </html>
      {{end}}
      `)
    err = t.ExecuteTemplate(w, "T", p) // This writes the client response
}

Then in main.go

   http.HandleFunc("/TopPicks", TopMoviesHandler)

TopPicks.html

{{define "TopPicks"}}
    {{template "header" .}}
    <div class="content">
    {{.TopMovies}}
    </div>
     {{template "footer" .}}
    {{end}}

What does work is this,

func aboutHandler(w http.ResponseWriter, r *http.Request) {
  display(w, "about", &Page{Title: "About"})
}

I can add a title to the page in the same way as I previously mentioned but using display()

And in the html template

<title>{{.Title}}</title>

How can I make this work for my json response?

like image 947
wuno Avatar asked Mar 12 '16 13:03

wuno


1 Answers

Looks like you are doing {{define "body"}}, but then asking ExecuteTemplate to execute "T" which isn't defined anywhere.

I think you want: t.ExecuteTemplate(w, "body", p)

That all said, if you just want to use multiple templates, you can do it by creating a master top level template, then parsing all the parts as sub templates.

Here's an example (on Play).

Easily changed to walk your file system and load all your templates, then you just execute the template matching the http.Request path.

package main

import "html/template"
import "os"
import "log"

var mainText = `
Normal page stuff
{{ template "_header_" . }}
{{ template "body" . }}
`

var bodyText = `
 Body has: {{ .Thing }}
`
var headerText = `
 I am header text
`

type Stuff struct {
    Thing string
}

func main() {
    t := template.New("everything")

    // parse all templates you may want
    template.Must(t.New("/").Parse(mainText))
    template.Must(t.New("_header_").Parse(headerText))
    template.Must(t.New("body").Parse(bodyText))

    if err := t.ExecuteTemplate(os.Stdout, "/", Stuff{"I am a thing"}); err != nil {
        log.Fatal("Failed to execute:", err)
    }
}
like image 125
David Budworth Avatar answered Sep 29 '22 07:09

David Budworth