Search code examples
templatesscopehugostatic-site

.Site.Data values are not accessible inside a range block


So I just noticed that when I try to access something from .Site itself inside a range block it returns as null/blank.

Here's an example:

<div class="row weekday">
  {{ .Site.Data.company.social_media.whatsapp }}
  {{ range $entry := sort .Site.Data.events "order" "asc" }}
  <div class="col-sm-6 col-md-4 col-lg-4">
    {{ .Site.Data.company.social_media.whatsapp }}
    {{ partial "events_detail.html" (dict "entry" $entry) }}
  </div>
  {{ end }}
</div>

The first .Site.Data.company.social_media.whatsapp (before the range) renders a phone number.

The second .Site.Data.company.social_media.whatsapp (after the range) do not renders anything.

This same behavior happens in the partial events_detail.html. If I try to access the .Site from inside of the partial scope it renders a null. I also tried to pass it along on the (dict ...) but no lucky.

What Am I missing here?


Solution

  • I was missing how Hugo manage the scopes for the dot. You read a more in-depth explanation about this (and other important concepts) here:

    https://regisphilibert.com/blog/2018/02/hugo-the-scope-the-context-and-the-dot/

    In Resume is (extracted from the link above):

    The root context, the one available to you in your baseof.html and layouts will always be the Page context. Basically everything you need to build this page is in that dot. .Title, .Permalink, .Resources, you name it.

    Even your site’s informations is stored in the page context with .Site ready for the taking.

    But in Go Template the minute you step into a function you lose that context as your precious dot or context is replaced by the function’s own… dot.

    (...)

    Same goes here, once you’ve opened an iteration with range the context is the whatever item the cursor is pointing to at the moment. You will lose your page context in favor of the the range context.

    {{ range .Data.Pages }}
        {{/* Here the dot is that one page 'at cursor'. */}} 
        {{ .Permalink }}
    {{ end }}
    

    Luckily Hugo stores the root context of a template file in a $ so no matter how deeply nested you are within with or range, you can always retrieve the top context. In basic template file, it will generally be your page.

    {{ with .Title }}
        {{/* Dot is .Title */}} 
        <h1>{{ . }}</h1>
        {{/* $ is the top level page */}} 
        <h3>From {{ $.Title }}</h3>
    {{ end }}