Golang template and testing for Valid fields - templates

In Go's database/sql package, there are a bunch of Null[Type] structs that help map database values (and their possible nulls) into code. I'm trying to figure out how to test whether a struct field is null, or in other words, when its Valid property is false.
The recommended way to print a SQL field is to use the .Value property, like this:
<div>{{ .MyStruct.MyField.Value }}</div>
This works great.
But suppose I have something slightly more complicated, where I need to test the value against something else, for example:
<select name="y">
{{ range .SomeSlice }}
<option value="{{ . }}" {{ if eq $.MyStruct.MyField.Value .}}selected="selected"{{ end }}>{{ . }}</option>
{{ end }}
</select>
As it happens, this works great, too, unless .MyField is not Valid, in which case I get the error, "error calling eq: invalid type for comparison". The error makes sense, because Go can't compare a nil Field against another value (or something like that).
I would have thought the 'easy' solution would be to test first whether the Value is nil, and then compare it against what I need, like this:
<select name="y">
{{ range .SomeSlice }}
<option value="{{ . }}" {{ if and ($.MyStruct.MyField) (eq $.MyStruct.MyField.Value .)}}selected="selected"{{ end }}>{{ . }}</option>
{{ end }}
</select>
In this case, I get the same "error calling eq: invalid type for comparison". I guess that means .MyField "exists" even though the value of .MyField is not Valid. So, then I tried a half dozen other versions, mostly with the same error, for example:
<select name="y">
{{ range .SomeSlice }}
<option value="{{ . }}" {{ if and ($.MyStruct.MyField.Valid) (eq $.MyStruct.MyField.Value .)}}selected="selected"{{ end }}>{{ . }}</option>
{{ end }}
</select>
At this point, I'm realizing I really don't understand how to test for the existence of a valid field at all. I'd appreciate any help you might have.
Thanks.

The and function in Go templates is not short-circuit evaluated (unlike the && operator in Go), all its arguments are evaluated always. Quoting from text/template package doc:
and
Returns the boolean AND of its arguments by returning the
first empty argument or the last argument, that is,
"and x y" behaves as "if x then y else x". All the
arguments are evaluated.
This means that the {{if}} action of yours:
{{ if and ($.MyStruct.MyField) (eq $.MyStruct.MyField.Value .)}}
Even though the condition would be evaluated to false if $.MyStruct.MyField is nil, but eq $.MyStruct.MyField.Value . will also be evaluated and result in the error you get.
Instead you may embed multiple {{if}} actions, like this:
{{if $.MyStruct.MyField}}
{{if eq $.MyStruct.MyField.Value .}}selected="selected"{{end}}
{{end}}
You may also use the {{with}} action, but that also sets the dot, so you have to be careful:
<select name="y">
{{range $idx, $e := .SomeSlice}}
<option value="{{.}}" {{with $.MyStruct.MyField}}
{{if eq .Value $e}}selected="selected"{{end}}
{{end}}>{{.}}</option>
{{end}}
</select>
Note:
You were talking about nil values in your question, but the sql.NullXX types are structs which cannot be nil. In which case you have to check its Valid field to tell if its Value() method will return you a non-nil value when called. It could look like this:
{{if $.MyStruct.MyField.Valid}}
{{if eq $.MyStruct.MyField.Value .}}selected="selected"{{end}}
{{end}}

Related

Get Value for Specific Select Option in Django Template

I am trying to get the value for a select option in my django template. I can iterate through an object like this:
<select id="id_name" name="name">
{% for x, y in form.fields.name.choices %}
<option value="{{ x }}">{{ y }}</option>
{% endfor %}
</select>
but is there any way to get a specific value eg; form.fields.name.choices.2? without looping? Thanks!
You can try
form.fields.name.choices.queryset.values.2
to get third element in a dict with your choices. Or you use
form.fields.name.choices.queryset.values_list.2
to get the choice as tuple.
See here https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values and here https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values-list

.Site.Data values are not accessible inside a range block

So I just noticed that when I try to access something from .Site itself inside a range block it returns as null/blank.
Here's an example:
<div class="row weekday">
{{ .Site.Data.company.social_media.whatsapp }}
{{ range $entry := sort .Site.Data.events "order" "asc" }}
<div class="col-sm-6 col-md-4 col-lg-4">
{{ .Site.Data.company.social_media.whatsapp }}
{{ partial "events_detail.html" (dict "entry" $entry) }}
</div>
{{ end }}
</div>
The first .Site.Data.company.social_media.whatsapp (before the range) renders a phone number.
The second .Site.Data.company.social_media.whatsapp (after the range) do not renders anything.
This same behavior happens in the partial events_detail.html. If I try to access the .Site from inside of the partial scope it renders a null. I also tried to pass it along on the (dict ...) but no lucky.
What Am I missing here?
I was missing how Hugo manage the scopes for the dot. You read a more in-depth explanation about this (and other important concepts) here:
https://regisphilibert.com/blog/2018/02/hugo-the-scope-the-context-and-the-dot/
In Resume is (extracted from the link above):
The root context, the one available to you in your
baseof.html and layouts will always be the Page context. Basically
everything you need to build this page is in that dot. .Title,
.Permalink, .Resources, you name it.
Even your site’s informations is stored in the page context with .Site
ready for the taking.
But in Go Template the minute you step into a function you lose that
context as your precious dot or context is replaced by the function’s
own… dot.
(...)
Same goes here, once you’ve opened an iteration with range the context
is the whatever item the cursor is pointing to at the moment. You will
lose your page context in favor of the the range context.
{{ range .Data.Pages }}
{{/* Here the dot is that one page 'at cursor'. */}}
{{ .Permalink }}
{{ end }}
Luckily Hugo stores the root context of a template file in a $ so no
matter how deeply nested you are within with or range, you can always
retrieve the top context. In basic template file, it will generally be
your page.
{{ with .Title }}
{{/* Dot is .Title */}}
<h1>{{ . }}</h1>
{{/* $ is the top level page */}}
<h3>From {{ $.Title }}</h3>
{{ end }}

Passing a value with whitespace from an html page to a view

I'm populating a dropdown box with values from a model as follows (abbreviated):
<select name="dropdown">
{% for thing in storedvalues %}
<option value={{ thing.name }}>{{ thing.name }}</option>
{% endfor %}
</select>
<input type="submit" value="Filter" id="bbutton"/>
and in the view...
def testpage(request):
if request.method == 'POST':
result = request.POST.get('dropdown')
print("hey this is the value: ", result)
selected_result = Song.objects.filter(name=result)
return render(request, 'testpage.html', {'selected_result': selected_result,})
This mostly works correctly. I select a value from a dropdown list and it returns the all of the data relating to the selected value. However when a value has white space in it, any characters following the white space are lost. I'm not sure how to go about fixing this.
If anyone could point me in the right direction it would be much appreciated
Put double quotes around the value otherwise the browser is going to interpret the field as set to empty as such: (yes, I'm using " thing.name" as the value for thing.name - not confusing at all)
<option value="" thing.name=""> thing.name</option>
With the quotes it'll be interpreted as:
<option value=" thing.name"> thing.name</option>
So just add a couple doublequotes and you'll be golden.
<option value="{{thing.name}}">{{ thing.name }}</option>

Selecting previous item in dropdown

I'm building a database search engine in Laravel and I am having some problems getting Laravel to select the previously selected item in a dropdown.
Using the template builder options I can make the select like this, and it does what I want it to do:
{{ Form::select('bomserial', $bomserials, Input::get('bomserial'), array('class' => 'pure-input-1', 'tabindex' => '3')) }}
The "Input::Get('bomserial')" makes it re-select the previously selected option in the dropdown after the form has been submitted, but building the input this way means I can't use the "selected disabled" option, so I opted to build the select like this instead:
<select name="bomserial" class="pure-input-1" tabindex="3">
<option selected disabled>BOM Serial</option>
#foreach ($bomserials as $bomserial)
<option value="{{ $bomserial->serial }}">{{ $bomserial->serial }} - {{ $bomserial->job_desc }}</option>
#endforeach
</select>
This produces a better looking menu and allows for the use of a default option, but now I can no longer re-select the previous option after the form has been submitted. How can I get around this?
Since you're not using the Form builder anymore, you have to manually take control of selecting the correct option.
Based on your existing logic, you're looking at something like this: if the bomserial is not in the input, select the placeholder; if the bomserial is in the input, select the bomserial option that matches the input.
<select name="bomserial" class="pure-input-1" tabindex="3">
<option {{ Input::has('bomserial') ? '' : 'selected' }} disabled>BOM Serial</option>
#foreach ($bomserials as $bomserial)
<option value="{{ $bomserial->serial }}" {{ Input::get('bomserial') == $bomserial->serial ? 'selected' : '' }}>{{ $bomserial->serial }} - {{ $bomserial->job_desc }}</option>
#endforeach
</select>

html/template if range index clause

I've got this template that parses multiple items of a slice onto the page. It does that really well.
However, I now want to use the very same template to parse a single value of the slice, based on the range index. The slice is used in multiple files so I can't just .Execute it like Slice[1:2]
{{ $bpi := .Index}}
{{ range $i, $elmt := .Slice }}
{{ if $bpi.Equals $i }}
<div>{{ .SliceContent }}</div>
{{ end }}
{{ end }}
From what I've read is that the template isn't ment for computation, but if you've got a range index and if-statements in the html/template package it seems to me that I must be doing something wrong. I can write a FuncMap ofcourse, no problemo. But it doesn't seem right to me given these facts.
I am using something like this to conditionally include a default image or the first from a supplied slice of pictures. So I think this will provide you with the basis to do what you want. I check the slice has values, pulling the Nth item using the {{index .Slice n}} syntax as follows:
{{ $idx := 2}}
{{if .Pictures}}
<img src="{{if .Pictures}}{{index .Pictures $idx}}{{end}}" alt="supplied first picture">
{{else}}
<img src="http://fpoimg.com/200x200?text=Placeholder(FPOimg.com)" alt="default picture">
{{end}}
Therefore you can do the following:
{{ $bpi := .Index}}
{{ if .Slice }}
{{ index .Slice $bpi }}
{{ end }}