How to prevent: "can't evaluate field x in type *hugolib.Page"

What is the correct way to prevent: ‘can’t evaluate field x in type’?

I’m trying to make a reusable card component. And there are 3 situations how a link provided to the component.

  1. RelPermalink
  2. .Params.link
  3. .link

The first two situations are easy to handle, but on the third one, I’m always getting errors when the current page doesn’t have .link field.

{{ .Scratch.Set "link" .RelPermalink }}
{{ if .Params.link }}
  {{ .Scratch.Set "link" .Params.link }}
{{ end }}
{{ if .link }}
  {{ .Scratch.Set "link" .link }}
{{ end }}

How can I prevent this behavior?

Try using with instead of if

{{ .Scratch.Set "link" .RelPermalink }}
{{ if .Params.link }}
  {{ .Scratch.Set "link" .Params.link }}
{{ end }}
{{ with .link }}
  {{ .Scratch.Set "link" . }}
{{ end }}
``
Is also resulting in:

``` can't evaluate field link in type *hugolib.Page ```

Also note that .link would not be a proper reference for the parameter of a content file. Such a reference is typically used when calling data files.

You have to call it as .Params.link

Oh and BTW the scratch constructs can be rewritten with the much simpler variable overwrites that were introduced in Go 1.11

The third option is when using it in a range

products:
  - title: Debiteurenbeheer
    link: debiteurenbeheer
{{ with .Params.products}}
  {{ range $index, $element := .}}
    {{ partial "components/cards/text.html" . }}
  {{ end }}
{{ end }}

Try .Params.products.link

Nice, replaced the scratch constructs with the variable overwrites. Much cleaner!

Using .Params.products.link isn’t working. And also if it would work, it isn’t very scalable. There are other arrays that I wan’t to render.

I just don’t understand why Hugo isn’t accepting this

{{ with .link }}
  {{ $link :=  . }}
{{ end }}

You would expect that it just skips this link when not valid.

Let try to clarify a few more things.

I’m building a text card that I want to use on multiple occasions through my Hugo website.

Situation 1
On a list template where I’m using a range function that loops over my posts. And I want to link the card to the post.

{{ range $index, $page := where .Data.Pages.ByWeight "Type" "partners" }}
	{{ partial "components/cards/text.html" . }}
{{ end }} 

In partial i’m using:
{{ $link := .RelPermalink }}

Situation 2
On a list template where I’m using a range function that loops over my posts. And I want to link to a custom param.

{{ range $index, $page := where .Data.Pages.ByWeight "Type" "partners" }}
    {{ partial "components/cards/text.html" . }}
{{ end }} 

In partial i’m using:

    {{ with .Params.link }}
      {{ $link := . }}
    {{ end }}

Situation 3
In a template where I’m looping over a range from a front-matter template.

Front matter

products:
  - title: Debiteurenbeheer
    link: debiteurenbeheer
  - title: Financiering
    link: financiering
{{ with .Params.products}}
{{ range $index, $element := .}}
{{ partial "components/cards/text.html" . }}
{{ end }} 
{{ end }}

In partial i’m using:

{{ with .link }}
  {{ $link :=  . }}
{{ end }}

Problem
The problem occurred when the card/text partial called on a page without font-matter range. I’m just totally lost on how to make this work.

Current partials/components/cards/text.html code

{{ $link := .RelPermalink }}
{{ with .Params.link }}
  {{ $link := . }}
{{ end }}
{{ with .link }}
  {{ $link :=  . }}
{{ end }}
<a href="{{ $link }}" >....</a>

Try it like this:

{{ $link := .RelPermalink }}
{{ with .Params }} <!-- Page-type context passed to partial -->
  {{ with .link }} <!-- Params.link provided; override previous --> 
    {{ $link = . }}
  {{ end }}
{{ else }} <!-- products map provided as context to partial -->
  {{ with .link }}
    {{ $link = . }}
  {{ end }}
{{ end }}


LINK: {{ $link }}

1 Like