Dynamically filter a taxonomy by term

Listing pages with a particular taxonomy term, by weight and reversed is easy enough.
One way:

{{ $taxonomy := .Site.Taxonomies.taxonomyname.termname }}
{{ range $taxonomy.Pages.ByWeight.Reverse }}
    {{ .Render "mypartial"}}
{{ end }}

But how do you go about doing that dynamically – in crude terms, and coming from Drupal’s phptemplate I want to do something like

{{ $term := .Params.taxonomyname }} // to get the taxonomy terms applied to this content
{{ $taxonomy := .Site.Taxonomies.taxonomyname.$term }}
{{ range $taxonomy.Pages.ByWeight.Reverse }}
     {{ .Render "minatura"}}
{{ end }}

This doesn’t work, I know, but I can’t figure out how to make it work.

What I’m trying to do: I have a single.html template for a particular content type and I want to display links to all pages that have the same term as the content I’m viewing AND order it by weight, reversed.

This works nicely in my default taxonomy.html template:

 {{ range .Data.Pages.ByWeight.Reverse }}
   {{ .Render "minatura"}}
 {{ end }}

But of course you’d need to pass the specific term on a content page…

And I have successfully used intersect to get a list of pages with the same term but can’t figure out how to sort it byWeight, reversed:

{{ $term := .Params.taxonomyname }}
{{ range .Site.Recent }}
{{ $page := . }}
{{ $has_common_tags := intersect $term .Params.taxonomyname | len | lt 0 }}
  {{ if $has_common_tags }}
     {{ .Render "minatura"}}
  {{ end }}
{{ end }}

So that should be as clear as mud :confused:

The second case, if you define .Params.taxonomyname as a single string value (not an array). How about replacing

{{ $taxonomy := .Site.Taxonomies.taxonomyname.$term }}

to

{{ $taxonomy := index .Site.Taxonomies.taxonomyname $term }}

And the last case, I think you can get pages sorted by weight by using {{ range .Site.Pages.ByWeight }} instead of {{ range .Site.Recent }}

Well, .Params.taxonomyname is an array, but even slicing that down to the first term with ‘first’ doesn’t seem to work for me – I guess it stays an array (or a slice at least). It seems like index should happily accept a slice, but I can’t get that to work either.

Swapping .Site.Recent for .Site.Pages.ByWeight does indeed work, but adding .reverse to get the full desired effect results in pages being returned in triplicate, and doesn’t list all the relevant pages…very weird.

So I’m still scratching my head over this. Reading Hugo docs it seems like ‘where’ should also do the job:


Something like

{{ range where .Site.Pages "term" "termname" }}
   {{ .Content}}
{{ end }}

But I can’t even get that to work.

Increasingly feeling I should really have taken the time to learn some Go before tackling Hugo’s go templates :frowning:

OK, so playing with index as you suggested I know have the following (the taxonomy is called ‘oggetti’, ‘fiori’ is the term name:

{{ $termname := "fiori" }}
{{ $taxonomy := index .Site.Taxonomies.oggetti $termname }}
{{ range $taxonomy.Pages.ByWeight.Reverse }}
  {{ .Render "minatura" }}
{{ end }}

This hardcoded $termname works, but isn’t actually any use – still can’t seem to get a working dynamic $termname.

.Params.oggetti is currently defined in content front matter as an array.
The obvious thing of converting the first term in .Params.oggetti to a string:

 {{ $termname := string(.Params.oggetti[0]) }}

Results in an ‘incomplete template’ error from hugo. I assume because go template won’t allow string().

At this point it seems my work tomorrow is going to involve going back over my content and converting the taxonomy terms back to strings :confused:

first function always returns a slice so it can’t be used for picking the first value up. Instead of it, index .Params.taxonomyname 0 may work but it requires all pages have at least one taxonomy word.

I use following code in my template to add a list of pages which have one of the tags of the page. It may be something hint

{{ range .Site.Pages }}
  {{ $has_common_tags := intersect $.Params.tags .Params.tags | len | lt 0 }}
  {{ if and $has_common_tags (ne $.Permalink .Permalink) }}
    <li>
      <a href="{{ .RelPermalink }}">{{ .Title }}</a>
      <small>
        {{ .Date.Format "2006-01-02" }}
        <ul>
          {{ range .Params.tags }}
            <li><a href="/tags/{{ . | urlize }}">{{.}}</a></li>
          {{ end }}
        </ul>
      </small>
    </li>
  {{ end }}
{{ end }}

tags is same as taxonomyname in your case. It is defined and expected as an array. The code checks all pages in the site and if a page has the same taxonomy word of rendering page, add it as <li> element. To avoid listing the same page multiple times, I use ne $.Permalink .Permalink condition. $.Permalink means {{ $page := . }} {{ $page.Permalink }}, just a shortened version. Staring $. is similar to absolute path, can refer outside range and starting . is context related path.

I confirmed it works if {{ range .Site.Pages }} is replaced by {{ range .Site.Pages.ByWeight.Reverse }}.

One of the issue of this is that it can’t limit the number of the pages listed on because checking all pages is required not to miss pages and there is no way to count in range loop.

Thanks.
Surely “ne $.Permalink .Permalink” prevents listing the page you’re on rather than prevents listing multiple times?

I’ve modified your code to fit my taxonomy, and to removed the check against permalink since I want all of the items listed. Works, better than before – there are no duplicates – but still produces a different order than the taxonomy listing. Which seems nonsensical since they both are supposed to be listing by weight.

Here’s the code for two blocks, the upper of which gives the result I want, the lower is your code modified:

                  <div class="oggetti-simili">
                    <h3>Oggetti simili</h3>
                    <ul class="minatura clearfix">
                    {{ $termname := "fiori" }}
                    {{ $taxonomy := index .Site.Taxonomies.oggetti $termname }}
                    {{ range $taxonomy.Pages.ByWeight.Reverse }}
                        {{ .Render "minatura" }}
                    {{ end }}
                    </ul>
                  </div>

                  <div class="oggetti-simili">
                    <h3>Another attempt</h3>
                    <ul class="minatura clearfix">
                    {{ range .Site.Pages.ByWeight }}
                      {{ $has_common_tags := intersect $.Params.oggetti .Params.oggetti | len | lt 0 }}
                        {{ if $has_common_tags }}
                          {{ .Render "minatura" }}
                        {{ end }}
                    {{ end }}
                    </ul>
                  </div>

You can see the results of this on my staging site here:
[Removed with an update]

The two blocks of thumbnails are what to look at. Why is the order of items different?

Edited to add: I want to maintain consistency with the main taxonomy listing layout, see [Removed with an update]

I gave up fighting with this, converted all my taxonomy terms back to strings and used index as per your suggestion in your first reply. Works well for now, I can always come back and improve it later.

Thanks for your help.