Use where with nested fields?

Shouldn’t I be able to use nested fields with a where statement?

{{$pages := where .Site.RegularPages ($.Param "foo.baz") "bar"}}

Sure, but where takes a page collection and then some strings – which may be the case in your example as well, but I suspect you mean:

{{$pages := where .Site.RegularPages ".Param.foo.baz" "bar"}}

That doesn’t work. Error executing "index.html" at <where .Site.RegularP...>: error calling where: Param is a method of type *hugolib.Page but doesn't satisfy requirements

Here’s a test case: https://github.com/budparr/hugo-test-2018-10-30

v0.50

Try Params instead of Param

1 Like

Thank you. That doesn’t work.

I got it to compile with this

{{$pages2 := where .Site.RegularPages .Params.foo.baz "bar"}}

But then no pages are shown under “Pages 2”

Edit: Nevermind. .Params.foo.baz needs to be a string as bep mentioned.

Edit 2: Yeah, not sure what to make of this error:

Building sites … ERROR 2018/10/30 12:39:44 Error while rendering “home” in “”: template: index.html:5:13: executing “index.html” at <where .Site.RegularP…>: error calling where: baz is neither a struct field, a method nor a map element of type interface {}

There are test cases covering this, but I’m not sure what the behaviour is when “foo.baz” is not set. I’m happy to say that this is one particular part of Hugo that I have not implemented.

/cc @tatsushid

1 Like

In this case, .Site.RegularPages is Pages which is actually []*Page so where works like following if .Site.RegularPages is quoted by double quote,

  1. Split dotted keys into array. It is used later, step 3, 4, 5…
  2. Call checkWhereArray() internal method to make a filtered collection
  3. checkWhereArray() calls Params() on each *Page and get its value. Params() should return map[string]interface{}
  4. Fetch a map value tied with “foo” key
  5. If “foo” returns a proper struct or map value, tries to evaluate it with “baz” key. In this case, tries to get “baz” field value or method call result on the struct or a map value of “baz” key.

At step 4, if there is no map value of “foo” key, it should return zero value of reflect package and it is treated as an error at beginning of evaluateSubElem method by IsValid() call. The error message should be “can’t evaluate an invalid value”

As commented, now it returns

error calling where: baz is neither a struct field, a method nor a map element of type interface {}

so “foo” returns something value but it is not a struct nor a map. It tells there is a page which has “foo” param key but it is not a map.

3 Likes