Hugo Scope Variable In Template

Aug 27, 2017
Use .Scratch to set outer scope variable or use as counter variable.

Scope variable

Hugo template has the limitation of scope variable, where you can't set a outer variable from a local scope. This is actually a limitation of Go Template.

A variable's scope extends to the "end" action of the control structure ("if", "with", or "range") in which it is declared, or to the end of the template if there is no such control structure. A template invocation does not inherit variables from the point of its invocation.

You might expect outerResult=true; for the following example, but the correct answer is outerResult=false; as the setting of variable within the if scope is a local scope and doesn't affect variable in the outer scope.

{{ $result := false }}
{{ if eq $result false }}
  {{ $result := true }}
  {{/* innerResult=true; */}}
  innerResult={{ $result }};
{{ end }}
{{/* outerResult=false; */}}
outerResult={{ $result }};

With scope variable limitation, you can't count variable within a range loop as well. For the following example, innerCount will always be 1 (each loop is a new local scope) and outerCount is 0. innerCount can access $count variable of the outer scope, but it can't change it from the inner scope.

{{ $count := 0 }}
{{ range .Site.Pages }}
  {{ $count := add $count 1 }}
  {{/* innerCount=1; */}}
  innerCount={{ $count }};
{{ end }}
{{/* outerCount=0; */}}
outerCount={{ $count }};

Use .Scratch

.Scratch acts as a “scratchpad” to allow for writable page-scoped or shortcode-scoped variables.

Both innerResult and outerResult will return true as expected based on the logic flow.

{{ $.Scratch.Set "result" false }}
{{ if eq ($.Scratch.Get "result") false }}
  {{ $.Scratch.Set "result" true }}
  {{/* innerResult=true; */}}
  innerResult={{ $.Scratch.Get "result" }};
{{ end }}
{{/* innerResult=true; */}}
outerResult={{ $.Scratch.Get "result" }};

count will increment correctly for the following case.

{{ $.Scratch.Set "count" 0 }}
{{ range .Site.Pages }}
  {{ $.Scratch.Add "count" 1 }}
  innerCount={{ $.Scratch.Get "count" }};
{{ end }}
outerCount={{ $.Scratch.Get "count" }};

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.