How to get/set from a dict, and append to a slice?

I want to have a list of posts, grouped by year.

My thought to do this was to create a dict where the keys were the years, and the values were a list of pages. I would firstly go through all pages putting them into the dict, and secondly go through the dict and render the page.

My questions:

  • I can create an empty dictionary with {{ $PagesForYear := dict }} and I could access a particular element if I knew its name at compile-time with $PagesForYear.foo. However, my key is $year determined at run-time. Can I do something like {{ $PagesForYear.Set $year "foo" }}? Alas it doesn’t work.

  • The values would be lists of pages. I can initialize an empty list with {{ $pages = slice }}. (I also saw array in an example on the hugo site but didn’t find it in the reference documentation, so I have used slice so far). Once I’ve initialized my empty list, how do I append new elements to it? {{ $pages.Append "foo" }} does not work, neither does {{ append $pages "foo" }}.

If this is documented and I missed it, please excuse me. If you would be so kind as to point me to the documentation, so I can look there next time, I would be much appreciative.

FYI this is the code I have so far (which doesn’t work):

  {{ $PagesForYear := dict }}
  {{ range .Data.Pages }}
    {{ $year := (.Date.Format "2006") }}
    {{ $PagesForYear.Set $year (default (slice) ($PagesForYear.Get $year)) }}
    {{ ($PagesForYear.Get $year).Append . }}
  {{ end }}
  
  {{ range $year, $pages := $PagesForYear }}
    <h2>{{ $year }}</h2>
    <ul>
        {{ range $pages }}
          <li>....</li>
        {{ end }}
    </ul>
  {{ end }}

Thanks in advance!
Adrian

1 Like

Thank you! :slight_smile:

Since I just did this recently for my site, maybe this will help save you a little bit of time if it’s similar to the design you’re looking for:

<h1 id="page-top">{{.Section | title}}</h1>
{{ range .Data.Pages.GroupByPublishDate "2006"}}
        <h2 class="archive-year" id="{{.Key | urlize}}">{{.Key}}</h2>
        <ul>
            {{ range sort .Pages "PublishDate" "desc" }}
            <li class="content-list-item">
                <a href="{{.Permalink}}">
                    <section>
                        <header>
                        {{if gt (len .Title) 60}}
                        <h3><span class="long-title">{{.Title | markdownify}}</span></h3>
                        {{else}}
                        <h3>{{.Title | markdownify}}</h3>
                        {{end}}
                        <p>{{ .Description }}</p>
                        </header>
                    </section>
                </a>
            </li>
           {{ end }}
        </ul>
{{end}}

And then creating a table of contents for maybe a smoothscroll type deal since the {{.TableOfContents}} won’t help you in the same way as it does in single pages here…

<aside class="toc" id="toc">
    <div class="toc-wrapper">
    <a class="pagetop-link" href="#page-top">
        <header class="toc-header" id="toc-header">
            <h4 class="toc-title">Archive</h4>
        </header>
    </a>
        <div class="toc-contents">
            <nav id="TableOfContents">
                <ul>
                    <li>
                        <ul>
                        {{ range .Data.Pages.GroupByPublishDate "2006"}}
                            <li><a href="#{{.Key | urlize}}">{{.Key}}</a></li>
                        {{end}}
                        </ul>
                    </li>
                </ul>
            </nav>
        </div>
    </div>
</aside>

And then using jQuery and Velocity.js, since velocity will reduce your jank considerably on longer list pages…

$(document).ready(function() {
    // bind click event to all internal page anchors
    $('.toc a').on('click', function(e) {
        // prevent default action and bubbling
        e.preventDefault();
        e.stopPropagation();
        // set target to anchor's "href" attribute
        var target = $(this).attr('href');
        if (target == "#page-top") {
        		$(target).velocity('scroll', {
        			duration: 500,
        			offset: 0,
        			easing: 'ease-in-out'
        		})
        } else {
            // scroll to each target
            $(target).velocity('scroll', {
                duration: 500,
                offset: -60,
                easing: 'ease-in-out'
            });
        }
    });
});