I was wondering if it was possible to access a nested dictionary with the dotliquid library.
What I have got so far is this:
type Document = {
template : string
elements : Map<string, obj>
}with
static member Test = {
template = "{% for item in test %} {{ item[\"name\"] }} {% endfor %}"
elements =
Map.empty
|> Map.add "test" ([Map.empty |> Map.add "name" "Foo"] :> obj)
}
let genTemplate =
let doc = Document.Test
let template = Template.Parse(doc.template)
template.Render(Hash.FromDictionary(doc.elements |> Map.toSeq |> dict))
The expected out of this would be: Foo
but somewhat unsurprisingly I simply get an empty string.
if I simply access item
as opposed to item["name"]
I get the output ["name", "Foo"]
. So is there any way to do this in dotliquid? Any help would be most appreciated.
A relatively easy trick is to register a filter getName
which then lets you access the name
property of the nested dictionary using {{ item | getName }}
. A filter can be written as an F# method:
type Filters() =
static member getName(map:Map<string, string>) = map.["name"]
Template.RegisterFilter(typeof<Filters>)
If you now use the filter in your test template. Note that depending on your configured DotLiquid naming convention, you might need to use get_name
as the name (which is also the default):
type Document =
{ template : string
elements : Map<string, obj> }
static member Test =
{ template = "{% for item in test %} {{ item | get_name }} {% endfor %}"
elements =
Map.empty
|> Map.add "test" ([Map.empty |> Map.add "name" "Foo"] :> obj) }
With this, you get the result you were expecting:
let genTemplate =
let doc = Document.Test
let template = Template.Parse(doc.template)
template.Render(Hash.FromDictionary(doc.elements |> Map.toSeq |> dict))
Unfortunately, I'm not sure if there is a way to create parameterized filters - it might be that you'll have to write something like getName
for each key that you want to access.