Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass data between templates [duplicate]

I have simple case, where a templates (text/templates) includes another like this

`index.html`

{{ template "image_row" . }}


`image_row.html`

{{ define "image_row" }}

   To stuff here

{{ end }}

Now I want to reuse the image row template. Let's say I would like to pass a simple number, so that the image_row template builds up rows according to this number

I'd like to have something like that (where 5 is the additional argument)

index.html

{{ template "image_row" . | 5 }}

How could I achieve that in this case?

like image 617
xhallix Avatar asked Apr 15 '17 12:04

xhallix


2 Answers

I'm not sure whether there exists a builtin solution for passing multiple arguments to a template invocation but, in case there isn't one, you could define a function that merges its arguments and returns them as a single slice value, then you can register that function and use it in the template invocation.

Something like:

func args(vs ...interface{}) []interface{} { return vs }
t, err := template.New("t").Funcs(template.FuncMap{"args":args}).Parse...

Then, in your index.html, you would do this:

{{ template "image_row" args . 5 }}

And then inside your image_row template you can access the arguments with the builtin index function like this:

{{ define "image_row" }}

   To stuff here {{index . 0}} {{index . 1}}

{{ end }}

https://play.golang.org/p/gkdtvvJ1bb

like image 156
mkopriva Avatar answered Sep 22 '22 19:09

mkopriva


There is no builtin for this. You can add a function that creates a map and use that in the child template:

func argsfn(kvs ...interface{}) (map[string]interface{}, error) {
  if len(kvs)%2 != 0 {
    return nil, errors.New("args requires even number of arguments.")
  }
  m := make(map[string]interface{})
  for i := 0; i < len(kvs); i += 2 {
    s, ok := kvs[i].(string)
    if !ok {
        return nil, errors.New("even args to args must be strings.")
    }
    m[s] = kvs[i+1]
  }
  return m, nil
}

Add it the function to the template like this:

t := template.Must(template.New("").Funcs(template.FuncMap{"args": argsfn}).Parse(......

Use it like this:

{{template "image_row" args "row" . "a" 5}}{{end}}

{{define "image_row"}}
     {{$.row}} {{$.a}}
{{end}}

Run it in the playground

The advantage of using a map is that the arguments are "named". The advantage of using a slice as described in another answer is that the code is much simpler.

like image 24
Bayta Darell Avatar answered Sep 21 '22 19:09

Bayta Darell