Use a variable to pick which partial to use - handlebars.js

I'm looking to load a partial based on a variable that is in the front matter data of the content page that i have. I've been able to get handlebars to pass back the correct variable name from in side the page but it will not then process the resulting string as a request to a partial:
<div class="sub-column">{{> (rhs1) }}</div>
this then just outputs the content of the variable rather than then going to find the partial it is referring to. I have also tried is using {{{ }}} but this has not helped.
Is this possible or am I going about this the wrong way?

It seems to me this is your issue ...
From the documentation available here : http://handlebarsjs.com/partials.html
Subexpressions do not resolve variables so whichPartial must be a function. If a simple variable has the partial name, it's possible to resolve it via the lookup helper.
{{> (lookup . 'myVariable') }}

I had to use a helper function to return the partial:
fs.readFileSync('src/partials/'+content+'.html', 'utf8');
this then allowed the system to recognise that we wanted to point to the partial.

Related

How to render partials/helpers *inside* a string variable?

Say I've got the following template/scenario:
{{partial-container container}}
{{{content.html}}}
{{#each content.partials}}
{{this}} // <-- here I'd like to render partials that users requested.
{{/each}}
Goals
[Done] I want to render a block of text, html-escaped, using the html property.
From the JSON, we also get a list of "partials" to render, but I can't figure out how to make this work.
Ideally, the syntax would be something like this:
{{partial-container container}}
{{{content.html}}}
{{#each content.partials}}
{{ > {{this}} }}
{{/each}}
But that throws a syntax error. Is there any way to interpret the contents of a variable as the name for a partial to render (and do so)?
I am assuming that your "list of partials" is an array of names matching with registered partials. Something like:
"partials": ["fooPartial", "barPartial", "fooPartial"]
The Handlebars documentation states that partials can be dynamically selected using a subexpression, but this subexpression must be a function that returns the partial name. This means that something as simple as {{> (this)}} will not work because our this is the string value of our partial name and not a function.
I see two ways of achieving our goal.
Option 1: Map the partial names to functions
If we have the ability to modify the data we are sending to our template, we could map the partial names into functions that return the name:
"partials": ["fooPartial", "barPartial", "fooPartial"].map(partialName => () => partialName)
These functions would allow us to dynamically insert our partials into our template with {{> (this)}}.
See this fiddle for an example.
Option 2: Use the lookup helper
If modifying our input data is not an option, we can use the Handlebars built-in lookup helper. The trick here is that, within our #each loop, we must step-up a context-level to get our partials array and then use the #index helper variable to get the partial name at the current index. The template would become:
{{#each content.partials}}
{{> (lookup ../content.partials #index)}}
{{/each}}
See this fiddle for an example.

Want to pass a variable to a partial, that contains a helper name like if or ifequals

I would like to pass a partial a variable that contains a helper, so that the partial can better reused, However, my companies installed version of handlebars will not accept new helpers.
data eg:
{
"orderLines":[
{"unitPrice": "0.46","isItemUnavailable": "Y"},
{"unitPrice": "0.46"}]
}
Template 1:
{{> myPartial helpername="if" totest="isItemUnavailable"}}
Inside myPartial:
{{#each orderLines}}
{{#helpername totest}}
// stuff here if isItemUnavialable
{{/helper}}
{{/each}}
The problem as I see it, is that I cannot pass a variable to my partial in order to dynamically set a helper?
The outcome of the above is an error in the partial, saying it cannot find helper "helpername" even though it is supposed to render "if"
The partial passes the variable if. But when you place it beside a hash, it no longer accepts it as a variable with a value, but looks for #helpername as a registered helper, which then throws an error because there isn't one.

Render a meteor reactive variable from a database field

If I have a field in my DB that contains a string like "Hello {{currentUser}}," is there a way to allow that value to retain reactivity when rendered into a template? I am also looking to see if I can somehow inject my own variable into the output by running it through a helper and handling string replacement.
Thoughts?
One solution I've come up with thus far:
The message stored in the db is something like: "Hello, [user], how are you?"
I then render the message from the DB as usual with {{#each}} and a predefined template.
When the message is actually rendered, I pass it through a helper. The helper replaces all []'s with <span class="$1"></span> so that I can target each item directly.
Once the message template's rendered() is called, I know that the message body contains the cleaned and prepped content (with the spans), so I use this.$('.user').each() and loop over each instance of the spans.
I've also created a special template in my page called 'placeholderUser' that only contains a call to {{user}}. I've added Template.placeholderUser.user = function(){} to the code to pull through a value and maintain reactivity.
Whew! Now that I have the structure set up, when looping through in the "each," I can call:
UI.insert(UI.render(Template.placeholderUser), el), which will render the template in the given span and maintain all reactivity.
It's super hacky, but it works. Any other, better, solutions out there?

assemble: Access global variables in {{parseJSON}}

Let's say you have a partial of some sort, which uses a global variable:
<img src="{{assets}}/logo.png">
Once you include the partial with specific data, either {{parseJSON}} or external JSON data:
{{#parseJSON '{"demo": true}'}}
{{>navigation}}
{{/parseJSON}}
all global variables like {{assets}} "killed" or at least overridden. Is there any chance to have still access?
Thanks in advance!
this is a known "issue" with Handlebar's partials in that the context inside a partial only includes the passed in context and no parent context, etc.. you can read more about the issue here.
fortunately the Assemble team provides a {{partial}} helper that will allow access to a more "expected" context, including global properties. once this helper is installed, you use it in a slightly different way than a normal partial:
{{#parseJSON '{"demo": true}'}}
{{partial "navigation"}}
{{/parseJSON}}
note that the partial helper is invoked with the name of the partial to include as a string.
that all being said, a new version of Handlebars was just released (v2.0.0-alpha.1) that may provide support for this natively. check out the more recent posts of issue thread i linked to above.
hope this helps.
As a workaround, the other way to cope with this is to pass the parent context explicitly to the partial:
{{#..}}
{{>partial}}
{{/..}}
Yeah.

how to do a preg_replace in twig

I currently am trying to make a variable using the current url for the view. To get the url, I am using {% set uri = app.request.uri %} (uri being my variable which is the current url for that particular view). The thing is, I am only interested in what makes the url unique (the end of it - a unique object from an array - happens to be a uri), and not the beginning (path to my application). I was thinking I could use a preg_replace to do so, but TWIG doesn't have this function. Just wondering if someone would know how to accomplish what I am trying to do?
I'm new to Symfony (and fairly new to PHP), so my explanations may not be clear (sorry).
Ex.
{% set uri = app.request.uri %}
output: http://website.com/http://item.org/1
I want to modify the uri variable to ONLY have http://item.org/1 (and not the path to my website).
I'm thinking creating a Twig Extension with the preg_replace will allow me to do this ..but not sure if it's the best way to go (inexperienced).
Overall goal:
The unique value for "uri" in the view is appended to the websites path by another view from an array of objects ($results) with attributes, one being "uri". My ultimate goal is to only display all associated attributes (or row) for an object in my $results array. I was thinking I could do this by first creating a key (my uri variable) in a foreach, and returning the row in the array which matches this key. This is why I am trying to create a variable with the url so that I can use it as a key for my foreach loop to iterate over $results. I am NOT using a database or Doctrine.
Thank you ahead of time for the help!
The best way is to move the logic from template to the controller.
If you need preg_replace in twig you must create custom extension.
Someone seems to have created a Twig Extension for preg_replace, see https://github.com/victor-in/Craft-TwigPCRE
You can do it like that. It's a bit ugly but it works.
uri|split('base_path')|join('')

Resources