Closed paulrobertlloyd closed 4 years ago
In addition, this of course also means values that are false
will return empty strings:
page.data.foo: {{ page.data.foo | json }}
foo: {{ foo | json }}
gives:
page.data.foo:
foo: ""
@zachleat My apologies. I had a very insightful thought in the shower this morning; the bugs I’m finding in 11ty all relate to Liquid, and I’m using my own LiquidJS instance (v9.x). Sure enough, downgrading Liquid to use the built in version means the above issue no longer presents itself.
Linking this to PR #1058 as something to check when this upgrade is merged in.
Hmmm, actually no, this is still a problem, regardless of Liquid version. 😔
I have a url
value in my dataset, that returns either a string value, or undefined
. Assigning it’s value using eleventyComputed, I get a different result when I test for its truthiness. For example, using the template:
page.data.url returns {% if page.data.url %}truthy{% else %}falsy{% endif %}
url returns {% if url %}truthy{% else %}falsy{% endif %}
the following is output:
page.data.url returns falsy
url returns truthy
Here’s an even simpler example. With the given frontmatter:
foo: false
eleventyComputed:
foo: "{{ foo }}"
and the following template:
foo returns {% if foo %}truthy{% else %}falsy{% endif %}
the following is output:
foo returns truthy
So even though foo
has been set to be false
, once it’s computed, it becomes something else equating to a truthy value.
And there’s completely different behaviour regarding objects when using computed data and Liquid v6. In this case, it is possible to access computed object values.
So, with a geo
object that contains longitude
and latitude
values, and the following template:
<pre>
page.data.geo: {{ page.data.geo }}
geo: {{ geo }}
page.data.geo.longitude: {{ page.data.geo.longitude }}
geo.longitude: {{ geo.longitude }}
</pre>
the following is output:
page.data.geo: [object Object]
geo: [object Object]
page.data.geo.longitude: -0.370437
geo.longitude:
Tl;DR: Computed data != original data, regardless of Liquid version. Phew! My head’s spinning… 🤪
Ah sorry after a bead I think there are a few hefty confusing limitations here that need a little bit more love.
Considering this a blocker for 0.11
Did a somewhat hefty refactor of computed data for #973 but I haven’t had a chance to retest this issue specifically yet. If you get a chance can you use the latest GitHub and see if this is fixed for you? Don’t dig too deep if it’s not—I’ll circle back here before 0.11.0 ships
Tried testing this but ran into a new issue #1098 🤦🏼♂️
Another push has been pushed!
Now that the issue in #1098 has been fixed, I tried this again, but still appear to be getting the same result, sadly.
@paulrobertlloyd I would expect those template strings to operate how they are currently operating, I think. There are two forks right now to computed data: 1. Template strings (renders through a template engine) and 2. everything else (usually a JS function though)
In Liquid JS, rendering a variable that has false
as the value will still render a truthy string.
For example, here’s a test I just wrote that passes (has nothing to do with computed data):
test("Liquid Render a false #1069", async t => {
let fn = await new TemplateRender("liquid").getCompiledTemplate(
"{{ falseValue }}"
);
t.is(await fn({ falseValue: false }), "false");
});
Is that unexpected behavior to you? Either way this merits a warning in the docs.
TLDR: strings beget strings. If you want different primitives you need to use function
computed data.
I’m almost tempted to remove the template string method altogether, but it is the only way to use computedData in YAML front matter right now which is the price we’re paying here.
Thanks for looking at this, unfortunate to hear that it’s a limitation. However, the more I think about this, the more I think this is a symptom, not the cause.
This issue stems from addressing data which can come from a variety of different sources, be it global/directory data, collections, pagination, or frontmatter. It’s all a bit confusing, and throwing computed data into the mix is probably only making things more complicated, at least from my perspective.
Also, turns out I was also doing something really stupid. I didn’t think to add the pages generated by pagination to their own collection, and then query that collection directly, but instead tried to model page data in my global data files. I’ve stopped doing that now, and as a result have a better understanding of data is modelled across these different sources and methods.
Just do keep in mind that this limitation is template language specific and only in play when you use raw strings. If you use a JS function in your computed data you can return any arbitrary object.
Going to close this for now—let me know if you have more questions!
Nope, all good on this front! 😃
TLDR: strings beget strings. If you want different primitives you need to use
function
computed data.
I believe it's necessary to reflect this in the documentation. As of now it's unclear that we can get only string values in the front matter.
Is your feature request related to a problem? Please describe. I have a dataset of addresses, and some of its values are objects. For example:
Generating pages from data, I paginate over these values, aliasing the paginated item to
page
.So that I can use the same variables across shared templates and includes – both for pages generated from both files and data – I use
eleventyComputed
to reassign these values to shorthand variables:However, it appears that Eleventy converts computed variables to strings. If I inspect both the ‘raw’ and computed template variables (using LiquidJS’s built-in
json
filter):[object Object]
is output:Describe the solution you'd like Not sure if there are any side effects to this, but a (Liquid) variable in
eleventyComputed
should have the same output as a (Liquid) variable in a template.BONUS REQUEST: It’d sure be nice if templates could use ‘longhand’ variables as well as ‘shorthand’ ones, i.e.
{{ page.data.title }} == {{ title }}
(this would also bring parity with the equivalent variables used in collection loops). That way, I wouldn’t need to create these computed shorthand variables in the first place!