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

huangapple go评论71阅读模式
英文:

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

问题

我正在尝试构建一个类似Reddit的网络论坛。有顶级帖子和回复,回复可以有回复,依此类推。

一个板块的结构如下:

var board map[string]*Post

以及一个Post的结构:

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

我该如何使用模板来遍历嵌套的Replies切片(要记住每个*Post都包含一个包含*PostsReplies切片,依此类推)?

我目前的进展:

<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>

这只允许我遍历两层回复(并且如你所见使用了重复的代码),我需要能够遍历任意层级的Replies

英文:

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:

&lt;div id=&quot;posts&quot;&gt;                                              
  {{ .Title  }}  
  {{ .Body  }}    
                                                                                
  &lt;ul&gt;                                                        
  {{ range $key, $value := .Replies }}                        
    &lt;li class=&quot;post&quot;&gt;                                         
      &lt;div class=&quot;postHead&quot;&gt;                                  
        &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{ $value.ID }}&lt;/b&gt;&lt;/div&gt;   
      &lt;/div&gt;                                                  
      &lt;div class=&quot;postBody&quot;&gt;{{ $value.PostNum }}&lt;/div&gt;        
    &lt;/li&gt;          
                                       
  &lt;ul&gt;                                   
  {{ range $key, $value := $value.Replies }}                  
    &lt;li class=&quot;post&quot;&gt;                                         
      &lt;div class=&quot;postHead&quot;&gt;                                  
        &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{ $value.ID }}&lt;/b&gt;&lt;/div&gt;   
      &lt;/div&gt;                                                  
      &lt;div class=&quot;postBody&quot;&gt;{{ $value.PostNum }}&lt;/div&gt;        
    &lt;/li&gt;                                                     
  {{ end }}                                                   
  &lt;/ul&gt;                                                       
                                                              
  {{ end }}                                                   
  &lt;/ul&gt;                                                       
&lt;/div&gt;                                                        

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.

答案1

得分: 7

要递归遍历一个层次结构,可以使用一个执行自身的命名模板。在下面的示例中,模板"replies"执行"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 示例

英文:

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 &quot;main&quot;}}
&lt;div id=&quot;post&quot;&gt;                                              
  {{.Title}}  
  {{.Body}}
  {{template &quot;replies&quot; .Replies}}
&lt;/div&gt;
{{end}}

{{define &quot;replies&quot;}}
   {{if .}}
      &lt;ul&gt;
      {{range . }}                                  
         &lt;li class=&quot;post&quot;&gt;                                         
           &lt;div class=&quot;postHead&quot;&gt;                                  
             &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{.Title}}&lt;/b&gt;&lt;/div&gt;   
           &lt;/div&gt;
           &lt;div class=&quot;postBody&quot;&gt;{{.Body}}&lt;/div&gt;
           {{template &quot;replies&quot; .Replies}}
         &lt;/li&gt;
      {{end}}
      &lt;/ul&gt;
   {{end}}
{{end}}

Playground Example

答案2

得分: 4

你刚刚定义了一个递归数据类型。你可以通过定义一个递归模板来渲染它:

{{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>
英文:

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

{{define &quot;replies&quot;}}
  &lt;ul&gt;
    {{ range $key, $value := . }}
      &lt;li class=&quot;post&quot;&gt;
        &lt;div class=&quot;postHead&quot;&gt;
          &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{ $value.ID }}&lt;/b&gt;&lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;postBody&quot;&gt;{{ $value.PostNum }}&lt;/div&gt;
      &lt;/li&gt;

      {{template &quot;replies&quot; .Replies}}
    {{end}}
  &lt;/ul&gt;
{{end}}

&lt;div id=&quot;posts&quot;&gt;
  {{ .Title  }}
  {{ .Body  }}

  {{ template &quot;replies&quot; .Replies }}
&lt;/div&gt;

huangapple
  • 本文由 发表于 2017年2月22日 02:25:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/42375121.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定