How to access global data from within the .Params scope?

Hello guys,
I have a price-list, output in partial “config.html”.

{{ with .Params }}
...
{{ partial "config.html" . }}
...
{{ end }}

The price-list consists of the specific part, stored in the page’s .Params, and general part, shown in many pages, that I want to store in a globally accessible data file.
The problem is, the config.html has no access to anything outside of .Params scope.
I hope the dict function can be used to access the general part of the price-list - but I can’t find a clear explanation how to use it. It would be great if someone can show me how to use it and solve my problem!
Thanks in advance!

You can use data templates https://gohugo.io/templates/data-templates/

Basically, store your shared data in ./data in a toml, yaml or json file.

for example, say your general prices are in ./data/pricelist.yaml
You can then access it from anywhere as

{{ range Site.Data.pricelist }}
... access fields with dot notation like .field
{{ end }}

Here’s a real life example of it in action:

with a sample data file here:

Thank you @yaythomas - my problem is accessing global data from withing the local .Params scope. So far I can either access data from .Params or from .Site.Data.prices. But I can not access .Site.Data.prices data from within .Params scope.
The only global variable I could access from within .Params scope was {{ .Site.Title }}. But so far I could not use to access anything else.

aaah, okay. You mean you’re trying to get to it inside your config.html partial. check out this awesome article by Hugo guru @regis on context, the ., the $ and flinging these around as arguments to partials: https://regisphilibert.com/blog/2018/02/hugo-the-scope-the-context-and-the-dot/

So, in your case:

{{ with .Params }}
...
{{ partial "config.html" dict("page" $  "params" .) }}
...
{{ end }}

And then inside your partial, the parent’s page context under .page and the params under .param

So, in your partial:

{{ $prices := .page.Site.Data.prices }}

By the way, not sure exactly what you’re doing with .Params in the outside with and whether you’re doing some sort of loop where the current iterator is important, but if not, you could just pass the entire parent context to the partial like so:

{{ with .Params }}
...
{{ partial "config.html" $ }}
...
{{ end }}

Hello @yaythomas,
thank you, this looks much closer to what I’m looking for.
So, now I have

{{ with .Params }}
...
{{ partial "config.html" (dict "page" $  "params" . ) }}
...
{{ end }}

[/quote]
AFAIK the $ lets my query look outside of the local scope and get data from a global variable.
dict is a function that lets me quote some key - value pairs from some dictionary. But where is it?
And what are “page” and “params” here?

I have a pricelist located in /data/price.yml that holds key - value pairs like
itemname1: 10.00
itemname2: 10.00
How I quote those pairs in my config.html?

Besides, you mention the expression
{{ $prices := .page.Site.Data.prices }}
What is it used for, where and how I can use it?

A part of my price-list should be sourced from the local .Params, and another part should be sourced from /data/price.yml
The problem can be solved either by this way, or by sourcing both specific and global parts from /data/price.yml - which may be possible if I find a way to use content filename (like i7-5500U.md) to pick its price from /data/price.yml.
If you have any idea - let me know!

Regarding your espression

{{ with .Params }}
...
{{ partial "config.html" $ }}
...
{{ end }}

what do you mean by “parent context” - where it should be located and what it can look like?

Thank you

lot of ideas here! I’m going to answer all of them best I can, but nothing I say here is the definitive “best” prescriptive solution for you, it sounds like you got some more complex data structures and considerations so it’s up to you to find the best fit for you. So I’m trying to give you some ideas and options and roughly how you would go about doing it in Hugo, but you’ll have to use this as a starting point to see what works for you. In other words, don’t expect anything I write here just to work by magic after a copy paste!

So starting from the bottom of your questions up:

If you do this:

{{ with .Params }}
...
{{ partial "config.html" $ }}
...
{{ end }}

Then you can have:

{{/* this is in config.html */}}
<p>my front matter field is: {{ .Params.myfieldname}}</p>
<p>Item 1 price is: {{ .Site.Data.price.itemname1}}</p>

next question up:

The problem can be solved either by this way, or by sourcing both specific and global parts from /data/price.yml - which may be possible if I find a way to use content filename (like i7-5500U.md) to pick its price from /data/price.yml.

You could use a where to pick something from your data file - see help here collections.Where | Hugo. You could even do this using the filename, or you could compare against a front-matter field.

{{ $name := .File.ContentBaseName }}
{{/* alternatively, pick your itemname from front-matter */}}
{{ $name := .Params.itemname }}
<p>this is item {{ $name }}</p>
{{ range where .Site.Data.prices "name" "==" $name }}
    <p>the price is: {{ .price }}</p>
{{ end }}

For this to work, your ./data/prices.yaml file would need to look something like this:

- name: item1
  price: 123.45
- name: item2
  price: 678.90

next question:

{{ $prices := .page.Site.Data.prices }}
What is it used for, where and how I can use it?

This is what would go in your partial file config.html. This actually answers your other questions:

…lets me quote some key - value pairs from some dictionary. But where is it?. . .And what are “page” and “params” here?

“page” and “params” are just arbitrary names you give to the parameters you pass to your partial inside the dict. You access them using these names. I just picked them because they’re descriptive. So when you’re in your partial, you access them using these names, e.g to access a param in your partial you go .params.myfieldnamehere or to access the page level you go .page.[PageLevelAnythingGoHere]

Hello @yaythomas, thank you for the info. As to your expression {{ partial “config.html” $ }} - it throws an error.
As to your other suggestions - I’m trying them.
I will give you some more details about my situation:

Here is a more detailed fragment of desktop.html partial

{{ with .Params }}
     <form id="form1" method="post" accept-charset="UTF-8">           
    {{ partial "configdesktop.html" . }}
     </form>
{{ end }}

Here is a more detailed fragment of configdesktop.html partial

<select class="order form-control border-0" id="select-1" required>
	<option id="BB01" value="" selected>{{ .subtitle1 }}</option>
	<option id="BB02" value="">{{ .subtitle2 }}</option>
	<option id="BB03" value="">{{ .subtitle3 }}</option>
	<option id="BB04" value="">{{ .subtitle4 }}</option>
</select>
<select class="order form-control border-0" id="select-2" required>
	<option value=""> {{ .RAMopt }}</option>
	<option id="RAM1" value="">{{ .RAMopt1 }}</option>
	<option id="RAM2" value="">{{ .RAMopt2 }}</option>
	<option id="RAM3" value="">{{ .RAMopt3 }}</option>
</select>

<script>
var m = {{ .margin }};
var pBB01 = {{ .price1 }};
var rBB01 = (pBB01 * m).toFixed(2);
document.getElementById("BB01").value = rBB01;
</script>

I can source all this data from .Params, but it will create a lot of redundancy, as RAM prices will be repeated in each desktop’s .Param.

So, the 1st select should be sourced from a model’s .Params, while the 2nd select should be sourced from /data/prices.yml

But there is also margin value, that should be sourced from config.toml

Here I’ve found the test reference that gets the value from /data/prices.yml from within .Params scope:

{{ with .Params }}
     <form id="form1" method="post" accept-charset="UTF-8">
    {{ $.Site.Data.prices.desktop.RAMprice1 }}           
    {{ partial "configdesktop.html" . }}
     </form>
{{ end }}

but it works only in this location. If I put it into configdesktop.html - it no longer gets the value. But I need it there to provide values for the 2nd select!

you’re almost there!

{{ with .Params }}
    <p>this is subtitle1 from front-matter: {{ .subtitle1 }}</p>
    <form id="form1" method="post" accept-charset="UTF-8">
        {{ partial "configdesktop.html" $ }}
    </form>
{{ end }}

And then, in layouts/partials/configdesktop.html:

<p>inside configdesktop.html</p>
<p>this is subtitle1: {{ .Params.subtitle1 }}</p>
<p>this is subtitle2: {{ .Params.subtitle2 }}</p>
<p>This is RAMprice 1: {{ .Site.Data.prices.desktop.RAMprice1 }}</p>
<p>This is RAMprice 2: {{ .Site.Data.prices.desktop.RAMprice2 }}</p>

Wow, incredible! It worked! Thanks a million! :grinning:
You know, Hugo has docs, but those are for people who understand hints.
While I need samples. Thank you once again! :+1: :+1: :+1:

1 Like