Passing index state to Render in Range

Scenario: Get a set of pages, iterate over them, rendering a layout. The layout should render specific classes to swap the order of elements.

Problem: $order is always set to order-1. Additionally, when running printf "%s" I get <nil> for both $idx and $.Scratch.Get "index"

index.html

// Set index to 0
{{ $.Scratch.Set "index" 0 }}
{{ range first 6 (sort $solutions ".Params.weight") }}
    // Bump index by 1
    {{ $.Scratch.Set "index" (add (int (.Scratch.Get "index")) 1) }}

    // Render the summary.html layout
    {{ .Render "summary"}}
{{ end }}

summary.html

{{ $idx := $.Scratch.Get "index" }}
{{ if modBool $idx 2 }}
    {{ $.Scratch.Set "solutions-order" "order-1" }}
{{ else }}
    {{ $.Scratch.Set "solutions-order" "" }}
{{ end }}
{{ $order:= $.Scratch.Get "solutions-order" }}
...
<div class="{{ $order }}">
    Content that should take order-1
</div>

A few things…

First, you have a context problem. With this:

{{ $.Scratch.Set "index" (add (int (.Scratch.Get "index")) 1) }}

you are setting a Scratch on the home page, not on the current page in the range.

Second, you can use .Store instead of .Scratch so that the value will survive rebuilds when running hugo server.

Third, I recommend using variables instead of .Store whenever possible. The syntax is cleaner, and it’s easier to reason.

So I would do this:

index.html

{{ $solutions := where site.RegularPages "Type" "solutions" }}
{{ range $k, $_ := first 6 (sort $solutions ".Params.weight") }}
  {{ .Store.Set "index" (add $k 1) }}
  {{ .Render "summary"}}
{{ end }}

summary.html

{{ $idx := .Store.Get "index" }}
{{ $order := "" }}
{{ if modBool $idx 2 }}
    {{$order = "order-1" }}
{{ else }}
  {{$order = "x" }}
{{ end }}

<div class="{{ $order }}">
  ...
</div>

Final note, if I have to pass a value, I prefer to use partials.

{{ partial "summary.html" (dict "page" . "index" $index) }}

Thank you @jmooring your solution worked. I wasn’t aware of .Store. All in all, a much more elegant solution.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.