• No results found

Initializing View Templates

In document Web Development with Go.pdf (Page 103-106)

Template definition files have to be parsed before templates execute. Parsing the template definition files is a one-time activity; the files do not need to be parsed each time the templates execute. Here the files are parsed and put into a map in which each element represents the template file for rendering a particular page. Three HTML pages have to be generated, so three items are put into the map. The template definition files are parsed in the init function and are parsed with the Must helper function. Must is a helper that wraps a call to a function returning (*Template, error) and panics if the error is non-nil.

Chapter 5 ■ Working With go templates

Listing 5-12. Compiling View Template Files in init in main.go var templates map[string]*template.Template

//Compile view templates func init() { if templates == nil { templates = make(map[string]*template.Template) } templates["index"] = template.Must(template.ParseFiles("templates/index.html", "templates/base.html")) templates["add"] = template.Must(template.ParseFiles("templates/add.html", "templates/base.html")) templates["edit"] = template.Must(template.ParseFiles("templates/edit.html", "templates/base.html")) }

For each content page, the appropriate content file is parsed along with base.html. Listing 5-13 is a helper function that renders individual web pages.

Listing 5-13. Helper Function that Renders Templates in main.go

//Render templates for the given name, template definition and data object

func renderTemplate(w http.ResponseWriter, name string, template string, viewModel interface{}) { // Ensure the template exists in the map.

tmpl, ok := templates[name] if !ok {

http.Error(w, "The template does not exist.", http.StatusInternalServerError) }

err := tmpl.ExecuteTemplate(w, template, viewModel) if err != nil {

http.Error(w, err.Error(), http.StatusInternalServerError) }

}

Here the parameter name is used as the key for retrieving the template file from the map, while the parameter template is used for providing the template name when we execute the template. The renderTemplate function provides the type interface{} as the type for the data object, so you can pass any type as the data object for applying into the template. The type interface{} is known as an “empty interface” that can hold values of any type. This type is very useful when you pass values to a function parameter when you don’t know the type that you pass at runtime or you want to provide values of any type.

Rendering the Index Page

Let’s render the Index page to show the list of Note objects. Listing 5-14 is the template definition in index.html.

Listing 5-14. Template Definition in index.html {{define "head"}}<title>Index</title>{{end}} {{define "body"}}

Chapter 5 ■ Working With go templates

<p>

<a href="/notes/add" >Add Note</a> </p> <div> <table border="1"> <tr> <th>Title</th> <th>Description</th> <th>Created On</th> <th>Actions</th> </tr> {{range $key,$value := . }} <tr> <td> {{$value.Title}}</td> <td>{{$value.Description}}</td> <td>{{$value.CreatedOn}}</td> <td>

<a href="/notes/edit/{{$key}}" >Edit</a> | <a href="/notes/delete/{{$key}}" >Delete</a> </td> </tr> {{end}} </table> </div> {{end}}

Named definitions of two templates are defined: head and body. Both will be used by the base template defined in base.html. When the Index page is executed, the map object that contains the object of the Note struct in each element is passed. The range action is used to iterate through the map object. In the range action, two variables are declared for the key and value element that is referenced inside the range action. A range action must be closed with an end action.

When users request the route "/", the Index page is rendered by calling the getNotes request handler in main.go. Listing 5-15 shows the getNotes function.

Listing 5-15. Handler Function for Route “/” in main.go func getNotes(w http.ResponseWriter, r *http.Request) { renderTemplate(w, "index", "base", noteStore) }

In the getNotes handler function, the renderTemplate helper function is called for rendering the Index page. To call renderTemplate, the http.ResponseWriter object is provided as the io.Writer, the index for getting the parsed template for executing the Index page, the base for specifying the template definition to be executed, and the map object as the data object to apply to the template definitions.

When templates["index"] is called, you get the compiled template that was parsed by using the template definition files index.html and base.html. The base template definition is finally executed from the parsed template that is a nested template in which it takes the template definition from head and page defined in the index.html file.

Chapter 5 ■ Working With go templates

Figure 5-2 shows the Index page with the list of Note objects.

Note that Figure 5-2 shows the final result of the application after implementing all handler functions for the example web application. For the sake of the demo, a couple of values were added into the noteStore object.

In document Web Development with Go.pdf (Page 103-106)