Introduction to Data Templates
If you have studied HTML Templates in the previous article, then we will continue with data templates where we can display this data dynamically by using struct or map data. However, we need to know the changes in the template text. We need to know the name of the field or key that we will use to fill in the dynamic data in the template. We can mention the name of the field
or key
, for example {{.FieldName}}
.
Apply to Project Handler
We first create a template in the templates
folder by creating a new file name.html
with contents as follows.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ .Title }}</title>
</head>
<body>
<h1>Hello {{ .Name }}</h1>
</body>
</html>
If we look at the HTML code above, it is very simple, we will send the Title
and Name
data from the handler to the HTML template. Next, we create a handler function as below.
func TemplateDataStructHandler(w http.ResponseWriter, r *http.Request) {
t := template.Must(template.ParseFiles("./templates/name.html"))
t.ExecuteTemplate(w, "name.html", map[string]interface{}{
"Title": "Template Data Struct",
"Name": "Santekno",
})
}
If you want to use struct
, the difference is actually the same, namely that we send the template a struct
which we have defined as in the example below.
type Page struct {
Title string
Name string
}
func TemplateDataStructHandler(w http.ResponseWriter, r *http.Request) {
t := template.Must(template.ParseFiles("./templates/name.html"))
t.ExecuteTemplate(w, "name.html", Page{
Title: "Template Data Struct",
Name: "Santekno",
})
}
And don’t forget to also add the handler function to initiate mux
with a different endpoint like this.
mux.HandleFunc("/template-data-map", TemplateDataMapHandler)
mux.HandleFunc("/template-data-struct", TemplateDataStructHandler)
So we can run our program then open the browser and access this endpoint, then a page will appear with the title Data Struct Template
and an HTML tag called Santekno
.
http://localhost:8080/template-data-struct
http://localhost:8080/template-data-map
HTML Template Testing
The way we test the handler function that we have created is by using a unit test as below.
func TestTemplateDataMapHandler(t *testing.T) {
tests := []struct {
name string
want string
}{
{
name: "get from embed",
want: "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <title>Template Data Map</title>\n </head>\n <body>\n <h1>Hello Santekno</h1>\n </body>\n</html>",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
request := httptest.NewRequest(http.MethodGet, "http://localhost/file", nil)
recorder := httptest.NewRecorder()
TemplateDataMapHandler(recorder, request)
body, _ := io.ReadAll(recorder.Result().Body)
bodyString := string(body)
if !reflect.DeepEqual(bodyString, tt.want) {
t.Errorf("response = %#v, want = %#v\n", bodyString, tt.want)
}
})
}
}
func TestTemplateDataStructHandler(t *testing.T) {
tests := []struct {
name string
want string
}{
{
name: "get from embed",
want: "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <title>Template Data Struct</title>\n </head>\n <body>\n <h1>Hello Santekno</h1>\n </body>\n</html>",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
request := httptest.NewRequest(http.MethodGet, "http://localhost/file", nil)
recorder := httptest.NewRecorder()
TemplateDataStructHandler(recorder, request)
body, _ := io.ReadAll(recorder.Result().Body)
bodyString := string(body)
if !reflect.DeepEqual(bodyString, tt.want) {
t.Errorf("response = %#v, want = %#v\n", bodyString, tt.want)
}
})
}
}
In this unit test we ensure that the input sent from the handler matches the HTML template response sent.