简体   繁体   中英

Range through an arbitrary number of nested slices of structs in an HTML template in Go

I'm trying to build a web forum kind of like Reddit. There are top level posts with replies and the replies can have replies and so on.

A board looks like this:

var board map[string]*Post

and a Post :

type Post struct {
  Title string
  Body string
  ID string
  PostNum int
  Replies []*Post
}

How would I use a template to range through the nested Replies slices (keeping in mind that each *Post contains a Replies slice that contains *Posts that contains Replies and so on)?

What I have so far:

<div id="posts">                                              
  {{ .Title  }}  
  {{ .Body  }}    

  <ul>                                                        
  {{ range $key, $value := .Replies }}                        
    <li class="post">                                         
      <div class="postHead">                                  
        <div class="postTitle"><b>{{ $value.ID }}</b></div>   
      </div>                                                  
      <div class="postBody">{{ $value.PostNum }}</div>        
    </li>          

  <ul>                                   
  {{ range $key, $value := $value.Replies }}                  
    <li class="post">                                         
      <div class="postHead">                                  
        <div class="postTitle"><b>{{ $value.ID }}</b></div>   
      </div>                                                  
      <div class="postBody">{{ $value.PostNum }}</div>        
    </li>                                                     
  {{ end }}                                                   
  </ul>                                                       

  {{ end }}                                                   
  </ul>                                                       
</div>                                                        

This only allows me to range through two levels of replies (and as you can see uses duplicate code), I need to be able to range through an arbitrary number of levels of Replies .

To recurse down a hierarchy, use a named template that executes itself. In the following example, the template "replies" executes "replies" to display sub-replies:

{{define "main"}}
<div id="post">                                              
  {{.Title}}  
  {{.Body}}
  {{template "replies" .Replies}}
</div>
{{end}}

{{define "replies"}}
   {{if .}}
      <ul>
      {{range . }}                                  
         <li class="post">                                         
           <div class="postHead">                                  
             <div class="postTitle"><b>{{.Title}}</b></div>   
           </div>
           <div class="postBody">{{.Body}}</div>
           {{template "replies" .Replies}}
         </li>
      {{end}}
      </ul>
   {{end}}
{{end}}

Playground Example

You just have defined a recursive data type. You can render it by defining a recursive template:

{{define "replies"}}
  <ul>
    {{ range $key, $value := . }}
      <li class="post">
        <div class="postHead">
          <div class="postTitle"><b>{{ $value.ID }}</b></div>
        </div>
        <div class="postBody">{{ $value.PostNum }}</div>
      </li>

      {{template "replies" .Replies}}
    {{end}}
  </ul>
{{end}}

<div id="posts">
  {{ .Title  }}
  {{ .Body  }}

  {{ template "replies" .Replies }}
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM