Range makes an random output

Hello,
i have this kind of structure of one of my pages (foto.md)

---
title: "My Starter Template"
description: "This is the My Starter Template"
keywords: ['keyword4', 'keyword5', 'keyword6']
author: "Daniel"
tags: [ "foto" ]

tile:
  tile1:
    width: "full"
    type: "youtube"
    src: "images/some-image.jpg"
    youtube: "XXXXyyyXXXX"
    overlay: "Overlay-Text"
    overlay-origin: "top-left"
    header: "Header<br>with Subheading"
    content: "Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa."
  tile2:
    width: "full"
    type: "mp4"
    src: "videos/postproduction.mp4"
    overlay: "Postproduction"
    overlay-origin: "top-left"
    header: "Header<br>with Subheading"
    content: "Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa."
  tile3:
    width: "half"
    type: "social"
    size: "medium"
    src: "https://www.youtube.com/channel/"
    icon: "youtube"
    title: "Youtube"
  tile4:
    width: "half"
    type: "social"
    size: "medium"
    src: "https://vimeo.com/user"
    icon: "vimeo"
    title: "Vimeo"
  tile5:
    width: "full"
    type: "image"
    size: "medium"
    src: "images/some-image.jpg"
    overlay: "overlay-text"
    overlay-origin: "bottom-left"
    header: "Header<br>with Subheading"
    content: "Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa."
  tile6:
    width: "full"
    type: "image"
    size: "large"
    src: "images/some-image.jpg"
    overlay: "overlay-text"
    overlay-origin: "top-right"
    header: "Header<br>with Subheading"
    content: "Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa."
  tile7:
    width: "half"
    type: "image"
    size: "small"
    src: "images/dominik.jpg"
    overlay: "Video Dreh"
    overlay-origin: "top-left"
    header: "Dominik"
    content: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa."
  tile8:
    width: "half"
    type: "youtube"
    size: "small"
    src: "images/wrommer.jpg"
    youtube: "rfSv8Mzaeoo"
    overlay: "Image- und Werbefilm"
    overlay-origin: "top-left"  

---
# Photo

This is my <strong>Photo</strong> Page

and this is my layout template (single.html)

{{ partial "header.html" . }}

  {{ .Content }}

  {{ range .Params.tile }}
    {{ if eq .type "youtube" }}
      <h3>This is Youtube</h3>
      <h2>{{ .header }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

    {{ if eq .type "mp4" }}
      <h3>This is MP4</h3>
      <h2>{{ .header }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

    {{ if eq .type "social" }}
      <h3>This is Social</h3>
      <h2>{{ .header }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

    {{ if eq .type "image" }}
      <h3>This is Image</h3>
      <h2>{{ .header }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

  {{ end }}

{{ partial "footer.html" . }}

I have a few problems and i’m totally new to HUGO. Hope someone can answer me some questions.

  1. Every time i change the code a bit and save my files AND Hugo renders the page new… the order of my “tiles” (tile1, tile2, tile3…) is an other: “tile3, tile1, tile8…” / Next time “tile8, tile3, tile1…” But i want it just in an normal order (1,2,3,4,5,6,7,8).

  2. Is it possible to output some of the params with HTML Code? Fields like “header” or “content” have some HTML in it like “br” “strong”

  3. Is this the right way to work with HUGO? I want the content of a site in the file itself. There will be more sites like this for my agency-website: sites like “photo” “video-production” “seo” “3D”… and every file has a header with text and then tiles with images and some text next to them or as an overlay…
    Maybe there is an better way to organize the content?

Thank you very much for helping me. And sorry for my english. Its not my native language. Hope you understand everything.

greetings from germany

  • Daniel

I don’t know if what you want is possible. From what I recall, maps in Go are unsorted and how you define tile looks like a map to me.

If that understanding of me is correct, it wouldn’t be possible to fix this behaviour on Hugo’s end. But perhaps you can hardcode the 8 tiles in your template file with an if statement for each?

I think I understand you. This is possible with:

{{ if isset "header" }}
    {{ .Params.header | safeHTML }}
{{ end }}

Or with markdownify if you used Markdown formatting to specify the text for header:

{{ if isset "header" }}
    {{ .Params.header | markdownify }}
{{ end }}

Putting the content of a file inside that file itself is a good idea and is what people commonly do with Hugo.

I don’t know if there’s a right way to do this. Given Hugo’s flexibility there are probably multiple right ways to do this. I’m not really comfortable telling you what the right way is. If it works for you without much mental overhead then it’s the right way for you. :slight_smile:

1 Like

Hi,
thanks for your help, but " | safehtml " dont work

my code

{{ partial "header.html" . }}

  {{ .Content }}

  {{ range .Params.tile }}
    {{ if eq .type "youtube" }}
      <h3>This is Youtube</h3>
      <h2>{{ .header | safeHTML }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

    {{ if eq .type "mp4" }}
      <h3>This is MP4</h3>
      <h2>{{ .header | safeHTML }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

    {{ if eq .type "social" }}
      <h3>This is Social</h3>
      <h2>{{ .header | safeHTML }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

    {{ if eq .type "image" }}
      <h3>This is Image</h3>
      <h2>{{ .header | safeHTML }}</h2>
      {{ .content }}<br /><br / >
    {{ end }}

  {{ end }}

{{ partial "footer.html" . }}

ErrorMessage:

ERROR 2018/02/15 17:28:19 Error while rendering “page” in “othertemplate/”: template: theme/othertemplate/single.html:20:23: executing “theme/othertemplate/single.html” at : wrong number of args for safeHTML: want 1 got 0


If that understanding of me is correct, it wouldn’t be possible to fix this behaviour on Hugo’s end. But perhaps you can hardcode the 8 tiles in your template file with an if statement for each?

I dont want the content in the layout template. i want it just a sorted output and the info stays in the “foto.md” file. is this not possible… or an other solution, but not hardcoded in the template file?

BIG EDIT
“Think simple Daniel” :smiley:

Its just
{{ range sort .Params.tile }}

And now its sorted.
Thank you for your help.

But the problem with the SAFEHTML is still there. Maybe some has an idea?

BIG EDIT 2

This code works now. It would be nice if somebody could explan it to me like i am 4 years old :smiley:

{{ partial "header.html" . }}

  {{ .Content }}

  {{ range sort .Params.tile }}
    {{ if eq .type "youtube" }}
      <h3>This is Youtube</h3>
      <h2>{{ with .header }} {{ . | safeHTML }} {{ end }}</h2>
      {{ with .content }} {{ . | safeHTML }} {{ end }}<br /><br / >
    {{ end }}

    {{ if eq .type "mp4" }}
      <h3>This is MP4</h3>
      <h2>{{ with .header }} {{ . | safeHTML }} {{ end }}</h2>
      {{ with .content }} {{ . | safeHTML }} {{ end }}<br /><br / >
    {{ end }}

    {{ if eq .type "social" }}
      <h3>This is Social</h3>
      <h2>{{ with .header }} {{ . | safeHTML }} {{ end }}</h2>
      {{ with .content }} {{ . | safeHTML }} {{ end }}<br /><br / >
    {{ end }}

    {{ if eq .type "image" }}
      <h3>This is Image</h3>
      <h2>{{ with .header }} {{ . | safeHTML }} {{ end }}</h2>
      {{ with .content }} {{ . | safeHTML }} {{ end }}<br /><br / >
    {{ end }}

  {{ end }}

{{ partial "footer.html" . }}

Good idea, I didn’t even think of that. Nice to see you got it fixed!

When you use {{ .header | safeHTML }} this code executes on each and every page that Hugo renders based on that template. But perhaps not every have got a ‘header’ variable in it.

When a page doesn’t have a ‘header’ variable but Hugo tries to render the {{ .header | safeHTML }} code there’s an error. That’s because safeHTML is a function that expects some input to work with. But there’s no ‘header’ variable for that particular page, and so safeHTML got nothing to work with.

This is also what Hugo try to say with the error:

ERROR 2018/02/15 17:28:19 Error while rendering “page” in “othertemplate/”: template: theme/othertemplate/single.html:20:23: executing “theme/othertemplate/single.html” at : wrong number of args for safeHTML: want 1 got 0

Translation in regular English: safeHTML wanted to get 1 argument to do its job on. But it got 0 arguments. And so it failed.

Now when you use {{ with .header }} {{ . | safeHTML }} {{ end }} you create a bit of conditional Hugo template code that roughly says: 'when there’s a ‘header’ variable (.header), execute the code that’s between {{ with ... }} and {{ end }}'. But when the ‘header’ variable isn’t there, that code doesn’t run, and so the safeHTML function doesn’t execute.

When the ‘header’ variable is set, then with temporarily set the dot (.)
to that variable. That means we can use . inside the where...end code block to access the ‘header’ variable.

I hope this all makes some sense. :slight_smile:

So it looks like this:

<!-- Check if the 'header' variable is set in the current page.
    When it is, set the dot's value (.) to that variable. -->
{{ with .header }}

    <!-- Now process the 'header' variable, which we set to
        the dot, with safeHTML -->
    {{ . | safeHTML }}

{{ end }}

There’s more information on with here: with | Hugo

1 Like