Home > Mobile >  Use Random Int for a Photo in Go Template
Use Random Int for a Photo in Go Template

Time:11-30

I have a simple random integer in my code that I am passing to the template

            min := 1
            max := 1563
            Photo := rand.Intn(max - min   1)
            fmt.Println(Photo)

            tmpl.ExecuteTemplate(w, "index.html", struct {
                Pages        []Page
                CurrentPage  int
                TotalPage    int
                NextPage     int
                PreviousPage int
                LastPage     int
                ShowNext     bool
                ShowPrevious bool
                Photo        int
            }{

                Pages:        pages,
                CurrentPage:  pageIndex   1,
                TotalPage:    totalPaginationPage,
                NextPage:     pageIndex   1,
                PreviousPage: pageIndex - 1,
                LastPage:     totalPaginationPage - 1,
                ShowNext:     pageIndex 1 < totalPaginationPage,
                ShowPrevious: pageIndex-1 >= 0,
                Photo:        Photo,
            })

the idea is to randomize a photo (I have 1563 in the folder) so in my template

{{range .Pages}}

<div id="content">
  <div >
    <p>
      <div >

  
    
        <a href="{{.Slug}} ">    <img
        

        src="{{.Photo}}"
        alt=""
      /></a>
        </div>
        
        <div >
          <div >
<a href="{{.Slug}} " >{{.Title}} </a>
</div>

src="{{.Photo}}" crashes the template, is like if the variable is not properly passed. Perhaps the issue is that this is inside a loop so I need a random number per each article in order to display a photo ?

Is there any other way to do it directly in the template ?

Update

Thanks to the guidance I now have

min := 1
max := 1563
Photos := make([]int, len(pages))
for i := range Photos {
    Photos[i] = rand.Intn(max - min   1)
}
            

            tmpl.ExecuteTemplate(w, "index.html", struct {
                Pages        []Page
                CurrentPage  int
                TotalPage    int
                NextPage     int
                PreviousPage int
                LastPage     int
                ShowNext     bool
                ShowPrevious bool
                Photo        []int
            }{

                Pages:        pages,
                CurrentPage:  pageIndex   1,
                TotalPage:    totalPaginationPage,
                NextPage:     pageIndex   1,
                PreviousPage: pageIndex - 1,
                LastPage:     totalPaginationPage - 1,
                ShowNext:     pageIndex 1 < totalPaginationPage,
                ShowPrevious: pageIndex-1 >= 0,
                Photo:        Photos,   
            })

and in the template

{{range $idx, $page := .Pages}}


<div id="content">
  <div >
    <p>
      <div >

  
    
        <a href="{{.Slug}} ">    <img
        
 src="{{index $.Photos $idx}}"
               alt=""
      /></a>
        </div>
        
        <div >
          <div >
<a href="{{.Slug}} " >{{.Title}} </a>
</div>

<div >
  <p>

tags:
</p>
       
          <ul>
       
            <li>
  {{.Tags}}
          </li>
  

</ul>
</div>


<div >
{{.Date}} 

</div>

</div>
</p>
</div>

</div>



       
{{end}} 

also tried

      <a href="{{.Slug}} ">    <img
        
 src="/public/suisse/suisse{{index $.Photos $idx}}.jpg"
               alt=""
      /></a>

but unfortunately the templates stop executing as soon as I call

{{index $.Photos $idx}} 

I assume it is a typo of some sort from my side?

CodePudding user response:

The {{range}} action changes the dot, so {{.Photo}} inside the {{range .Pages}} will be resolved on the elements of .Pages.

Use $ to refer to the "outer", original value passed to the template execution:

src="{{$.Photo}}"

Although this is only an integer, you likely want to use it in a path or an URL, something like this:

src="/path/to/images?id={{$.Photo}}"

Note: If you want a different image for all pages, you have to pass a different number for each, not just a single one. Then add a Photo field to page, and then you can refer to it inside the {{range}} as {{.Photo}} as in your original code.

You wrote you can't modify Page as it comes from your database. If so, then either pass a slice of random numbers and access them with index like this:

min := 1
max := 1563
Photos := make([]int, len(pages))
for i := range Photos {
    Photos[i] = rand.Intn(max - min   1)
}

tmpl.ExecuteTemplate(w, "index.html", struct {
    Pages        []Page
    CurrentPage  int
    TotalPage    int
    NextPage     int
    PreviousPage int
    LastPage     int
    ShowNext     bool
    ShowPrevious bool
    Photo        []int
}{

    Pages:        pages,
    CurrentPage:  pageIndex   1,
    TotalPage:    totalPaginationPage,
    NextPage:     pageIndex   1,
    PreviousPage: pageIndex - 1,
    LastPage:     totalPaginationPage - 1,
    ShowNext:     pageIndex 1 < totalPaginationPage,
    ShowPrevious: pageIndex-1 >= 0,
    Photo:        Photos,
})

In template:

{{range $idx, $page := .Pages}}
    <a href="{{.Slug}} "><img
        src="{{index $.Photos $idx}}"
        alt=""/>
    </a>
{{end}}

Or register a random function which you can call from the template:

// Parse the template as you did, but first register a random function:
min, max := 1, 1563
tmpl, err := template.New("").Funcs(template.FuncMap{
    "random": func() int { return rand.Intn(max - min   1) },
}).ParseFiles("template-name.html")

And you can call it from the template like this:

{{range .Pages}}
    <a href="{{.Slug}} "><img
        src="{{random}}"
        alt=""/>
    </a>
{{end}}
  • Related