[SOLVED] Switch case in templates + using local shortcode variables with Scratch

Is there a Go switch-case syntax that can be used in Hugo templates and shortcodes in place of multiple if-else conditions?

In Hugo there is also with that is more terse.

I’m new to Hugo and Go in general, but I’m not sure with is exactly what I want: I want my shortcode to behave differently depending on a value of a shortcode parameter that can have several alternative values, and there are instances where I also want to configure a default behavior. If I understand your intention correctly, using with I can write something like this:

{{ $type := .Get 0 }}

{{ with (eq $type "A") }}
    ...
{ end }}
{{ with (eq $type "B") }}
    ...
{{ end }}
...

That works but it’s not exactly a switch case like in other languages, and I’m not sure it’s simpler or cleaner than using multiple if-else clauses. The advantage of if-else compared to this with implementation is that (a) The processing will stop when any of the conditions evaluates to true, which is more efficient. (b) It inherently supports a default-behavior alternative, while with would require additional code for that. Or am I missing something here?

Thanks

From the docs:

with
An alternative way of writing “if” and then referencing the same value is to use “with” instead. with rebinds the context . within its scope, and skips the block if the variable is absent.

In my opinion it’s much cleaner than writing multiple if/else or isset statements.

You can read more regarding Hugo conditionals over here: https://gohugo.io/templates/go-templates#conditionals

EDIT
Regarding default behaviour Hugo has a pipeline for that. See here: https://gohugo.io/templates/functions#default

In Go templates there are if, if else and else, but no switch.

  • Regarding the with documentation that you quoted from the Hugo docs, I have actually already read it but I don’t think it addresses the issues with using with for my specific use case. Assuming the parameter that I’m evaluating always exists, unlike switch-case syntax in other languages, I would still need to repeat the condition code for testing its value in each with clause (similar to if/else clauses), and end each clause with {{ end }}; and all the with clauses will be evaluated while with if-else the evaluation will stop when a match is found.

    Is my with example what you meant, or did you have another with construct in mind?

  • Thanks for pointing out the default function. That’s useful.

Your example is what I had in mind. But @bep has already answered that there is no switch in Go.

So I guess you have to make do with what’s available.

OK, thanks guys. Now I’ve run into another problem, which is probably related to my basic Hugo/Go ignorance:I tried using the code below to implement what I want, but the $id and $title variables are always evaluated to their initialization values (in this case, empty strings, but I tested using non-empty strings as well). I verified (using debug prints) that the relevant with clause is applied according to the value of the shortcode’s 0 parameter. However, the reassignments of the $id and $title variables in the with clauses (or outside of them) is not applied. I also wasn’t able to define these variables without initializing their values. I’m guessing there’s an error in my variable definition and/or assignment syntax, but I can’t figure it out. Perhaps you can point me in the right direction?

{{ $type := .Get 0 }}
{{ $id := "" }}
{{ $title := "" }}

{{ with (eq $type "new") }}
  {{ $id := "new-features" }}
  {{ $title := "New Features" }}
{{ end }}
{{ with (eq $type "enhancements") }}
  {{ $id := "enhance" }}
  {{ $title := "Enhancements" }}
{{ end }}
{{ with (eq $type "fix") }}
  {{ $id := "fixes" }}
  {{ $title := "Fixes" }}
{{ end }}

<a id="{{ $id }}"></a>
<h2>{{ $title }}</h2>

They’re empty because you’re not populating them with the variables.

Do this instead

{{ $id := .Get "id" }}
{{ $title := .Get "title" }}

I assume that you have corresponding title and id parameters in your shortcode.

I don’t have $id and $title shortcode parameters. These are local variables that I define in the shortcode. Therefore the .Get code that you suggested won’t work, as it’s suited for getting parameter values. I’m assuming there should be a way to define local shortcode variables and update their values conditionally, shouldn’t there?

How are you defining them? Show us an example.

You can also get them by position like you’re getting type.

I copied the full code in my previous message; the definition is in the second and third lines.
The initial assignment works, because I tested using non-empty strings in the definition and if I print the variable values the initialization strings are printed. The issue is that the reassignment to these variables (inside or outside of my with clauses) has no effect.

I meant an example of how you’re calling the shortcode in a content file with the variables defined. Not the shortcode itself.

But you should also bear in mind that shortcodes are rendered from the inside then out in Hugo.

I’m calling the shortcode like this: {{< release-notes-heading "new" >}}; (I also tested with % instead of </>, although the shortcode doesn’t include Markdown code). But why does the shortcode-call syntax matter when when the issue is with local variables? The parameter that I’m passing to the shortcode is evaluated correctly.

I’m not sure what you mean by this?

So “new” is a variable correct? If yes, you should be able to get it by position using .Get 1

See this for an explanation: Explanation of rendering order

No. new is a value of the unnamed 0 parameter, which I assign to a $type variable using .Get 0. Based on the value of this parameter, I want to create an HTML heading with specific text and ID, which I set differently depending on the value of the unnamed 0 parameter (e.g., “new”). Instead of repeating the heading + anchor HTML in each with clause but with a different text and anchor ID (as I currently do), I want to use local $id and $title variables, and then write the HTML code once, at the end, using the local variables to set the appropriate text and title (see my code).

1 Like

Thanks for this link. It definitely seems useful, but I don’t think it helps with my current issue, as there is no nesting or other template calls involved.

Right. The following syntax is untested but it should work for you.

{{ $type := .Get 0 }}
{{ with (eq $type "new") }}<a id="new-features"></a><h2>New Features</h2>{{ end }}
{{ with (eq $type "enhancements") }}<a id="enhance"></a><h2>Enhancements</h2>{{ end }}
{{ with (eq $type "fix") }}<a id="fixes"></a><h2>Fixes</h2>{{ end }}