Template Partials as Filters?

I am looking to use new Templates to replace some stuff that uses Genshi (python) for complex XML templates. In Genshi, you can define partials exposed as methods, allowing variables to be passed in and dynamically select child partials.

For example:

<foo py:def="one" someattrib="one" />
<foo py:def="two" someattrib="two" />
<foo py:def="three" someattrib="three" />
<foowrap py:def="wrapthis(var)">${var}</foowrap>

elsewhere you can then use this syntax in your xml template:

<stuff>
    ${wrapthis(two)}
</stuff>

which will generate:

<stuff>
    <foowrap>
        <foo someattrib="two" />
    </foowrap>
</stuff>

Essentially the argument for one partial was used within the partial to inject another partial. Suggestions on how best to achieve this with ServiceStack? Looks like it could probably be done with partials if each partial was a separate file, which will get to be a bit overkill if say I want to have xml-based colour injected with dozens of colour presets.

In trials for this approach, I see that partials cannot specify arguments (ie: default values in page header), but I can pass a value into a partial and use it to inject a global _layout variable, which does help some aspects.

Coding each py:def as a filter might do the trick too, but I can’t compile them, would need to be template-file based. Perhaps a notation to define filters within partials? Or named partials?

Curious to get your take on it.
thanks!

ps: need to add a new topic category dropdown item for ServiceStack.Templates. :wink:

For creating reusable code, Templates only supports partials and filters. Each partial does need to be in a separate file but they’re not expensive at runtime as they’re parsed, cached and evaluated in memory.

If you’re going to use a filter you’ll want to return IRawString, e.g. return xml.ToRawString(); so the XML response isn’t encoded.

ok, follow-up:

a) any way to specify argument in partials preamble (<!-- arg: 1 -->)
b) would there be a way to extend Templates to allow dynamic filters
c) a way to inject partial args into the resolution of next partial? {{ 'partials/{{arg1}}' | partials }} or something like that?

For © I might need to create my own find filter to concate variables perhaps…

All Templates features are documented at http://templates.servicestack.net everything’s interactive so you can easily try expressions / features out.

Partials are pages and has access to all its features in including Page arguments. You can also set a default value if one isn’t provided with:

{{ arg | default(1) | assignTo: arg }}

Not sure what you mean by dynamic filters, if you just mean change what filter is based which argument is supplied you can do with:

{{ arg1 | onlyIfExists | myfilter | assignTo: value }}
{{ arg2 | onlyIfExists | myfilter | assignTo: value }}

Which will only execute the custom myfilter when the argument exists. If you want to invoke something dynamic with reflection pass the argument in the filter and do what you need in C#.

I don’t understand what you mean by c), the way to define scoped arguments for partials is to use partial({ arg: 1 }), partials also can access arguments defined in the parent page and partial.

Let me add some clarifications:

in (a), I found that you cannot specify ‘default’ arguments in partials in the page header (eg: <!-- -->) as you can in layout/pages, but yes, you can pass arguments into the partial.

for (b) by dynamic I mean a way to define filters at run-time through files, as one might in vuejs, not just precompiled.

for ©, in a partial I’d like to use the value of an argument concatenated with another to form the name of a new partial (ie: loading partials several levels deep).

There is no code compilation in Templates. Filters are defined using C#, they can’t be created in pages.

Including a partials just executes a filter, you can modify the name as you would any string argument, e.g:

{{ 'my-partial-' | append(arg) | partial }
{{ 'my-partial/{0}/the-partial' | fmt(arg) | partial }
1 Like