Search code examples
htmlgomarkdownhugo

In HUGO, how do I get a the list of pages in a section from a partial view?


I'd like to think that this is a fairly simple idea, however I have been struggling with it for a while now. The idea is this: I have a bunch of single blog pages. On the right of the content in these pages, I want to have a list of the five latest blog posts as a partial view.

In my HUGO project, I have a file structure setup like the following:

content
|  |_ posts
|      |_ _index.md
|      |_ firstPost.md
|      |_ secondPost.md
|      |_ thirdPost.md
|      |_ fourthPost.md
|
layout
  |_ partials
        |_ footer.html
        |_ head.html
        |_ navbar.html
        |_ sidePosts.html
    posts
        |_ list.html
        |_ single.html
    index.html

  

My layout/posts/single.html page looks like the following:

<!DOCTYPE html>
<html>
    {{partial "head.html"}}
    {{partial "navbar.html"}}
    <body>
        <div class="container-fluid p-5">
            <a href="/posts" class="sub-font text-black-50"> << Back To Posts</a>
            <div class="row">
                <div class="col-lg-9">
                    <h1>{{.Title}}</h1>
                    <p class="text-black-50"><i>{{ dateFormat "Monday, Jan 2, 2006" .Date }}</i></p>
                    <hr>
                    {{ .Content }}
                </div>
                <div class="col-lg-3">
                    {{partial "sidePosts.html"}}
                </div>
            </div>
        </div>
    </body>
    {{partial "footer.html"}}
</html>

And my layout/partial/sidePosts.html looks like this:

<div class="container-fluid d-flex flex-column align-items-center my-5 text-center">
    <div class="row w-100">
        {{ range (where .Site.RegularPages "Section" "in" "posts") }}
            {{ .Title }}
        {{ end }}
    </div>
</div>

However, when I run this, I get this error:

error calling where: can’t iterate over <nil> failed to render pages

I've tried switching the types around, which where I'm looking, and different directories besides posts, but to no avail. I keep getting the same <nil> issue. I have a feeling it has something to do with the scope in which I'm searching; maybe theirs some global parameter I'm missing to gain access to the content of the project? I'm still new to HUGO so perhaps the answer is obvious, but I'm going to continue looking for a solution.

EDIT (Dec 27th, 2022):

I managed to get it working, just not in a partial view. What I did was just write what I wanted to do in the single template itself, instead of in a partial view. The code for layout/posts/single.html has been updated to:

<!DOCTYPE html>
<html>
    {{partial "head.html"}}
    {{partial "navbar.html"}}
    <body>
        <div class="container-fluid p-5">
            <a href="/posts" class="sub-font text-black-50"> << Back To Posts</a>
            <div class="row">
                <div class="col-lg-9">
                    <h1>{{.Title}}</h1>
                    <p class="text-black-50"><i>{{ dateFormat "Monday, Jan 2, 2006" .Date }}</i></p>
                    <hr>
                    {{ .Content }}
                </div>

                {{/*  START OF UPDATE: Dec 27th, 2022  */}}
                <div class="col-lg-3">
                    <h3 class="text-center text-black-50">Latest Posts</h3>
                    <div class="container-fluid">
                        <div class="row">
                            <div class="col-lg-12 d-flex flex-column align-items-center justify-content-center">
                                {{ range first 5 (where .Site.RegularPages "Section" "in" "posts") }}
                                    <a href="{{ .Permalink }}" class="text-center main-font main-color-font" style="cursor: pointer;">{{ .Title }}</a>
                                    <p>{{ .Summary }}</p>
                                    <hr>
                                {{ end }}
                            </div>
                        </div>
                    </div>
                </div>
                {{/*  END OF UPDATE: Dec 27th, 2022  */}}

            </div>
        </div>
    </body>
    {{partial "footer.html"}}
</html>

This works fine for my layout/posts/single.html pages, but what if I wanted to have something like this in a different directory: say the layout/contacts/single.html pages? Would I have to copy and paste the same code into that singles template? That's where my idea of having it as a partial view comes in. I would like to have this code, but in a partial view for more modularization and to keep it dry. And whenever I try and do that, I get a error calling where: can’t iterate over <nil> failed to render pages error.


Solution

  • You need to pass the context to your partial for your script to work. This is why you got it to work in the template, but not in the partial.

    {{ partial "sidePosts.html" }}
    

    should be:

    {{ partial "sidePosts.html" . }}
    

    The "." ("the dot") represents the context in Hugo. If you add it, your partial should be able to iterate over .Site.RegularPages

    See Partials Documentation here: https://gohugo.io/templates/partials/

    And this section about "the dot": https://gohugo.io/templates/introduction/#the-dot