Check multiple values in an array/object in bigcommerce using stencil - handlebars.js

I am trying to find the values in an array if the values are there need to remove and print those values. I had tried the below code but it is not working. Please advise
color_filter => color bowl_filter1 => bowl
{{#and (filter (split this.display_name '_') 'filter') (filter (split this.display_name '_') 'filter1') }}
{{#each (split this.display_name '_') }}
{{#and (if this '!=' 'filter') (if this '!=' 'filter1')}}
{{this}}
{{else}}
:
{{/and}}
{{/each}}
{{else}}
{{ this.display_name }}:
{{/and}}
Thanks in advance

If I am understanding this correctly, you are looking to chop off the underscore and everything after it?
In that case, you could simply use the following code, as it would accomplish this:
{{first (split display_name '_')}}:
And if you use underscores in other values and only want to remove it if filter is there after, you could use this code instead:
{{first (split display_name '_filter')}}:
Let me know if this helps, or if I am off-base here. It may help to have some extra context added here. For example, where are you doing this. Is this in the faceted search on the category page, based on custom fields of the products?

Related

Accessing an element within a list of Json objects using handlebars.js

"guests": [
{
"guestname": "john smith",
"is_active": false,
"guestheight": "175cm",
"guestprofile": "https://www.example.com"
},
{
"guestname": "david smart",
"is_active": false,
"guestheight": "175cm"
}
]
I would like to check if guestprofile exist. Given that I currently have a variable holding the index of the list we are trying to access here, namely itemIndex. So basically I'm trying to query if guests[itemIndex]["guestprofile"] in handlebars.js context.
If I make a direct reference like
{{#if guests.0.guestprofile}}
//do something
{{/if}}
its working fine. However, if I replace 0 with itemIndex like below, everything broke...
{{#if guests.itemIndex.guestprofile}}
//do something
{{/if}}
Currently I have also tried
{{#if (lookup guests itemIndex).guestprofile}}
//do something
{{/if}}
{{#if guests[itemIndex].guestprofile }}
//do something
{{/if}}
None of them actually worked. Please help, Thank you in advance!
You were so close with your lookup attempt.
The issue is that Handlebars does not allow you to chain a key onto a lookup subexpression as you are doing with (lookup guests itemIndex).guestprofile. It just doesn't resolve dynamic variables that way, which is the same reason why lookup has to be used instead of guests.itemIndex.guestprofile.
The part you missed is that you actually need two lookups - one to get the element of guests at itemIndex and the second to get the guestprofile of that element.
Your template needs to become:
{{#if (lookup (lookup guests itemIndex) 'guestprofile')}}
do something
{{/if}}
I have created a fiddle for your reference.

Can't use logical operators in handlebars #if statement?

I have the following code:
{{#if true}} An {{else}} A {{/if}
That's the entire template. It's loading fine. But notice the #if condition is simply true. If I put anything other than a literal there, it doesn't work. Any variable I put, any sort of programmatic expression like {{#if 3 > 5}}, it gives me a Parser Error:
Error: Parse error on line 36:
{{#if 3 > 5 }} An {{else}} A
---------------------^
Expecting 'CLOSE_RAW_BLOCK', 'CLOSE', 'CLOSE_UNESCAPED', 'OPEN_SEXPR', 'CLOSE_SEXPR', 'ID', 'OPEN_BLOCK_PARAMS', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'INVALID'
I can't figure that out. I even reduced it to just {{#if 3 > 5}} A {{/if}} and it still gives a parser error.
So I thought maybe you have to use a helper for this sort of thing, but I can't get any helper I register to work either.
Turns out the #if helper can only test for properties to be true or false – not arbitrary expressions[source], so you have to do everything with helpers. Just write a function to compare things with logical operators and return true or false.
And to save you some trouble, the syntax for calling helpers doesn't use parentheses, either....arguments are space-separated like in rails. So it looks like:
{{myHelperFunction myarg1 myarg2}}
And if you want to nest helpers, you need parens:
{{myOuterHelper (myInnerHelper myarg1 myarg2)}}
Last tip from me, if you want to nest your helper with an #if, you need parens, too:
{{#if (myHelper myarg1 myarg2)}} content {{/if}}

Keep leading 0 in Twig

In my database, I have a field containing the following data : 000010 (the type is integer)
In my twig tpl, I want to display it, then I do : {{ spending.documentName }}
But the browser displays "10". As if Twig was automaticcaly performing a trim on my data.
I tried {{ spending.documentName|raw }} but it doesn't work. I dont find anything on Google about how to keep leading 0 with Twig.
Does anyone know how to proceed ?
I think you must force the format (as your type is integer).
You can use the format filter :
{{ "%06d"|format(spending.documentName) }}
Or better create a twig extension (http://symfony.com/doc/current/cookbook/templating/twig_extension.html):
public function strpad($number, $pad_length, $pad_string) {
return str_pad($number, $pad_length, $pad_string, STR_PAD_LEFT);
}
It's clearer in your template :
{{ spending.documentName | strpad(6,'0') }}
You need to use the format filter.
Since placeholders follows the sprintf() notation, you should be able to convert sprintf('%06d', $integer); in PHP to {{ '%06d'|format($integer) }} in Twig.
Kinda late here, but ran into the same.
With twig 3.x you can use:
{{your.number | format_number({min_integer_digit:'2'})}}

TWIG how to get the first word of a string?

I've got a string and I want to
isolate the first word for styling with style1 and
display the rest of the string with style2 without the first word.
Something like that :
<span class="style1">{{ string|firstword() }}</span>
<span class="style2">{{ string|restofstring() }}</span>
Is it possible ? Thank you in advance.
I believe you can achieve this by using the split command in Twig. To split you need to identify the separator between two words. Assume your words are separated using a space. Then you can get the first and second words like this.
{{ "Monday Tuesday" | split(' ')[0] }}
Will return the "Monday"
{{ "Monday Tuesday" | split(' ')[1] }}
Will return the "Tuesday"
More about split :- http://twig.sensiolabs.org/doc/filters/split.html
Hope this helps,
Cheers!
I found it ! With split() and attribute() TWIG functions.
{% set array = article.titre|split(' ', 2) %}
<span class="style1">{{ attribute(array, 0) }}</span><!-- First word -->
<span class="style2">{{ attribute(array, 1) }}</span><!-- Rest of string -->
Thanks to Anjana Silva who give me the begginning of the idea.
As an alternative to the array syntax, you might find the first filter to be more idiomatic:
{{ "Hello Twig"|split(' ')|first }}

Handlebars, whitespace control

i want fine control of whitespace but still have readable templates.
Just wanted to see if other's solution to by simple use case.
{{name}}
{{#if age}}
, {{age}}
{{/if}}
# outputs {{name}} , {{age}}
# desire: {{name}}, {{age}}
https://github.com/wycats/handlebars.js/issues/479 - submitted a ticket which was closed.
Following the history from the pull request to add this feature it looks like this is the correct syntax:
<h4>
{{~#object~}}
Surrounding whitespace would be removed.
{{/object}}
</h4>
Result:
<h4>Surrounding whitespace would be removed.</h4>
There is also this syntax which trims only leading whitespace:
<h4>
{{~#object}}
Only leading whitespace would be removed.
{{/object}}
</h4>
Result:
<h4>Only leading whitespace would be removed.
</h4>
Just a comment to Brian answer, If you want to trim whitespace AND do not want handlebars to escape your expression at the same time, the correct syntax to be used is:
{{~{EXPRESSION}~}}
(trimming whitespace before and after the expression while not escaping it)
The Handlebar's Whitespace Control Documentation can be found here:
https://handlebarsjs.com/guide/expressions.html#whitespace-control
Template whitespace may be omitted from either side of any mustache statement by adding a ~ character by the braces. When applied all whitespace on that side will be removed up to the first handlebars expression or non-whitespace character on that side.
These two, comma-list examples would have the same output:
Case 1:
{{#each listItems as |item index|}}
{{#if (eq index 0)}}
{{~item.name~}}
{{else~}}
, {{item.name~}}
{{/if}}
{{/each}}
Case 2:
{{#each listItems as |item index|}}
{{#if (eq index 0)~}}
{{item.name}}
{{~else~}}
, {{item.name}}
{{~/if}}
{{/each}}
I think the cleanest implementation of this would be to add {{"\n"~}} where you want a hard-stop on new lines.
The "\n" can technically be anything except for empty, ie "". I used "\n" to make it clear what I am doing in the editor.
Example
Three empty lines after this
{{"\n"~}}
Three empty lines before this
Two empty lines before this. No empty lines after this.
{{~"\n"~}}
No empty lines before this.
Result
Three empty lines after this
Three empty lines before this
Two empty lines before this. No empty lines after this.No empty lines before this.
Basically, as others have said, any helper can be prefixed or suffixed with ~. Here, I've decided to pass a value that won't render as the helper ("\n") which allows us to pass ~ freely to control before and after whitespace.
Edit
Alternatively:
Handlebars.registerHelper(
'singleLineOnly',
function (options) { // "this" cannot be provided to inline function!
return options.fn(this).replace(/[\r\n]+/gm, '')
}
)
Handlebars.registerHelper(
'singleSpaceOnly',
function (options) { // "this" cannot be provided to inline function!
return options.fn(this).replace(/\s\s+/g, ' ')
}
)
Which will allow you to take something like this:
{{#each this}}
{{#singleLineOnly}}
{{#singleSpaceOnly}}
{{calculatedAmount}}
{{!an example comment}}
{{#if unitOfMeasure.translate}}
{{{unitOfMeasure.translate.value}}}
{{/if}}
{{!some random comment}}
{{#unless unitOfMeasure.translate}}
{{{unitOfMeasure.value}}}
{{/unless}}
{{!Some random comment}}
{{#ifNotEquals (lowerCase product.value) "other"}}
{{!If translated, use translated UOM}}
{{#if product.translate}}
{{{product.translate.value}}}
{{/if}}
{{!If not translated, use default UOM}}
{{#unless product.translate}}
{{{product.value}}}
{{/unless}}
{{/ifNotEquals}}
{{!just some more logic for example}}
{{#ifNotEquals (lowerCase ingredient.value) "other"}}
{{!If translated, use translated UOM}}
{{#if ingredient.translate}}
{{{ingredient.translate.value}}}
{{/if}}
{{!If not translated, use default UOM}}
{{#unless ingredient.translate}}
{{{ingredient.value}}}
{{/unless}}
{{/ifNotEquals}}
<br/>
{{/singleSpaceOnly}}
{{/singleLineOnly}}
{{/each}}
And end up with this:
1/2 oz. first ingredient <br/>
1 pump(s) another ingredient <br/>
3/4 oz. this ingredient <br/>
2 shot(s) that ingredient <br/>
last instruction <br/>
{{#singleLineOnly}} and {{#singleSpaceOnly}} can be used as a wrapper for any text. You'll most likely want to use these with ~ for additional before/after whitespace control. For example: {{~#singleLineOnly~}}
You can add a Handlebars Helper to trim() whitespace
{{#-}}
Surrounding whitespace would be removed.
{{/-}}
more background info: https://github.com/wycats/handlebars.js/pull/336

Resources