问题
Is it possible to achieve variable indirection in dust.js - and therefore to be able to use map-like functionality?
Imagine I have the following context to pass to Dust:
{
"keys": [ "Foo", "Bar", "Baz" ],
"data": [{
"date": "20130101",
"values": {
"Foo": 1,
"Bar": 2,
"Baz": 3
}
}, {
"date": "20130102",
"values": {
"Foo": 4,
"Bar": 5,
"Baz": 6
}
}]
}
And I want to achieve the following output (it would actually be a table, but I've skipped the <tr><td>
tags for brevity and replaced them with spaces and newlines):
Date Foo Bar Baz
20130101 1 2 3
20130102 4 5 6
I'm not sure how to loop over the keys
property, and use each value x
to look up data[i].values[x]
. I can get the desired output by hardcoding the keys:
Date{~s}
{#keys}
{.}{~s}
{/keys}
{~n}
{#data}
{date}{~s}
{values.Foo}{~s}
{values.Bar}{~s}
{values.Baz}{~s}
{~n}
{/data}
but the keys will be determined dynamically, so I can't hardcode them into the template. Is there a way to replace the lines that say values.Foo
etc., with something like the following:
{#data}
{date}{~s}
{#keys outerMap=values}
{outerMap.{.}}{~s}
{/keys}
{~n}
{/data}
This doesn't work as written; can I capture the output of {.}
(the value of the current key) and dynamically use it as (part of) the property name to resolve?
回答1:
So, the short answer is no, you can't do that in Dust.
Dust is meant to be a logicless language, and this is bordering on too much logic. Generally the answer to problems like this one is to update your JSON so it works correctly in Dust. This could be done easily in the example you have given, but could be much more difficult in a real world situation. Part of the power of Dust lies in its limitations.
If this answer doesn't work for you, you are welcome to submit a pull request on GitHub: https://github.com/linkedin/dustjs
回答2:
As smfoote says, this is not supported out-of-the-box in Dust.
However, I've realised that handlers can involve some elements of logic, and so it was relatively straightforward to write a handler to do dereferencing:
deref: function(chunk, context, bodies, params) {
chunk.write(params.obj[params.prop]);
}
This handler takes an obj
argument which is the object to use as an associative array; and the prop
parameter describing the key to look up from that object. With this handler function added to the context, I was then able to write the data part of the template as:
{#data}
{date}{~s}
{#keys}
{#deref obj=values prop=./}{~s}
{/keys}
{~n}
{/data}
This produces the correct output, by iterating over every key and passing it in as the property to read from the values
object.
I appreciate that some might consider this inappropriate given Dust's philosophy. However I don't think it constitutes particularly complex logic; indeed, it's something that could quite conceivably be part of a templating framework. Given that smfoote's suggested alternative of updating my JSON isn't an option (the template does not know what the keys will be in advance, so there is no way to write "static" references here), this seems like a reasonable approach.
来源:https://stackoverflow.com/questions/14462903/indirection-in-dust-js