Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have short circuit with and/or in text/template

I have this Go template:

{{ if and $b.Trigger $b.Trigger.Name }} 
  Name is {{ $b.Trigger.Name }}.
{{ else }}
  ...other stuff...
{{ end }}

I'm trying to get this template to do:

if b.Trigger != nil && $b.Trigger.Name != "" { ...

however it doesn't work, because as text/template godoc says, both arguments to and/or functions are evaluated.

When the $b.Trigger.Name is evaluated, it errors out because $b.Trigger can be nil. So it returns error:

template: builds.html:24:46: executing "content" at <$b.Trigger.Name>: can't evaluate field Name in type *myType

I tried refactoring this to:

{{ if and (ne $b.Trigger nil) (ne $b.Trigger.Name "") }}

and weird enough, this fails as well, it says I can't compare $b.Trigger with nil, which doesn't make sense because that field is a pointer type:

template: builds.html:24:31: executing "content" at <ne $b.Trigger nil>: error calling ne: invalid type for comparison

Any ideas?

like image 661
ahmet alp balkan Avatar asked Jun 16 '17 06:06

ahmet alp balkan


1 Answers

As Volker noted above, nest the ifs:

{{if $b.Trigger}}{{if $b.Trigger.Name}}
  Name is {{ $b.Trigger.Name }}.
{{end}}{{end}}

Or, more succinctly:

{{with $b.Trigger}}{{with .Name}}
  Name is {{.}}.
{{end}}{{end}}

Unfortunately, the above won't handle else clauses. Here's one (rather ugly) possibility:

{{$bTriggerName := ""}}
{{with $b.Trigger}}{{$bTriggerName = .Name}}{{end}}
{{with $bTriggerName}}
  Name is {{.}}.
{{else}}
  ...other stuff...
{{end}}

I looked to see if gobuffalo/plush could do this more elegantly, but as of 2019-04-30 it cannot.

like image 179
Chaim Leib Halbert Avatar answered Sep 21 '22 21:09

Chaim Leib Halbert