it took me a while to get the snippet working. I assume that all your content files have a non-empty string as title. Otherwise you might get an error message due to $firstChar.
I’ve annotated each step of the template logic so it’s easier understand and to modify the snippet:
<!-- create a list with all uppercase letters -->
{{ $letters := split "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "" }}
<!-- range all pages sorted by their title -->
{{ range .Data.Pages.ByTitle }}
<!-- get the first character of each title. Assumes that the title is never empty! -->
{{ $firstChar := substr .Title 0 1 | upper }}
<!-- in case $firstChar is a letter -->
{{ if $firstChar | in $letters }}
<!-- get the current letter -->
{{ $curLetter := $.Scratch.Get "curLetter" }}
<!-- if $curLetter isn't set or the letter has changed -->
{{ if ne $firstChar $curLetter }}
<!-- update the current letter and print it -->
{{ $.Scratch.Set "curLetter" $firstChar }}
<h3>{{ $firstChar }}</h3>
{{ end }}
-- {{ .Title }}<br>
{{ end }}
{{ end }}
That is a great example, thanks for the mini tutorial.
I have a question - it looks like you are creating custom variables - with $letters and $firstChar? I don’t see anything in the docs pertaining to what those are, all I found was Scratch. What are the $letters := type things and what is the difference between them and Scratch?
@digitalcraftsman Very nice, what a great example. Thanks for taking the time to make it.
Correct, that is creating variables. Those variables would only be available within the content of that snippet where as with Scratch, they’d exists throughout the Hugo build (so you could use them in other templates for example).
ok, good to know, I thought Scratch was only within the snippet.
So why then does his example include scratch as well as a regular variable? is there something limiting about the other variable that the whole thing could not be done with it?
Rather than {{ $.Scratch.Set "curLetter" $firstChar }} could it be {{ "curLetter" = $firstChar }}?
The thing is, that .Data.Pages.ByTitle gives 0 results, may be because as i’m searching posts on page template. And .Site.Pages.ByTitle gives tags pages that I don’t need. I did non figured out how to get all posts inside page template
I added the variable $firstChar simply for better readability and to keep the code DRY since it’s used in multiple places.
.Scratch is used to store the current letter beyond an iteration. An alternative approach would be to use a variable outside the loop, similar to $letters. However, as far as I know it’s not possible to reassign a variable in Go templates. Hence I had to use .Scratch.
My post have this structure
Blondie — Parallel Lines (1978)
Blackstreet — Blackstreet (1994)
Big Black — Songs About Fucking (1987)
I cut year string (substr .Title -2 4) but I need to do sort then as something like
{{ range sort .Site.RegularPages }}{{ substr .Title -2 4 }}
correct?
awesome, thanks for the explanation this has been a very helpful thread for me and I have no interest in the op’s idea, I just try to read everything in the hopes of finding little nuggets like this!
In your example you want to sort your content based on the year (in the title) instead of displaying them in alphabetical order, what my snippet does.
I guess it’s easier to add a new front matter parameter , e.g. year, that contains the year from the title. This way you can group your content based on a parameter defined in the content.
Thank you,
I just want to find solution without front matter
Get substring (1), sort (2) and group (3) (as in your example with alphabet order). First part seemed most tricky, but now I see that the most tricky is first part.