Twig number format without rounding decimals - twig

How is it possible in twig to format a number, without rounding off the decimals?
For example, if the user inputs
12345.35, output should be 12,345.35
12345.356, output should be 12,345.356
12345.3567, output should be 12,345.3567
I tried number_format filter but the first parameter is precision to which the decimals should be rounded to. If I use 12345.35|number_format(4, '.', ',') the result is 12,345.3500 which is not the desired output.

You should determine the number of decimals you have in the number before formatting it. Not quite obvious but I don't find another solution.
Try with this macro:
{% macro show_number(n) %}
{%- spaceless %}
{% set decimals = n | split('.')[1] | default('') | length %}
{{ n | number_format(decimals, '.', ',') }}
{% endspaceless -%}
{% endmacro %}
Runnable example here

Related

Macro causing white space in Jinja2?

I was expecting that this macro
{% macro join_them(first) -%}
{% set data = [] %}
{% if first not in ["", None, "None"] %}
{{ data.append(first) }}
{% endif %}
{% for arg in varargs %}
{% if arg not in ["", None, "None"] %}
{{ data.append(arg) }}
{% endif %}
{% endfor %}
{{' '.join(data)}}
{%- endmacro %}
Would render this
<td> * {{ join_them(docs["Author"]["Name"].title, docs["Author"]["Name"].first, docs["Author"]["Name"].middle, docs["Author"]["Name"].last, docs["Author"]["Name"].suffix) }}</td>
As this line, without the use of the macro, does
<td> * {{ ' '.join([docs["Author"]["Name"].title, docs["Author"]["Name"].first, docs["Author"]["Name"].middle, docs["Author"]["Name"].last, docs["Author"]["Name"].suffix])}}</td>
The non macro version is working fine, and outputing the name information correctly, but the Macro version is putting out white space and some "None" strings.
e.g.
<td> *
None
None
Computer Community
*</td>
<td>Computer Community </td>
Anyone have any suggestions on what I'm missing here? Or a better way to handle this? I don't typically use macros in Jinja2, but this seemed a perfect opportunity to do so.
The macro is indeed causing those blank lines, and you had the right approach already, you need to use whitespace control to remove them. You only placed them at the beginning and the end of your macro but note that:
You can also strip whitespace in templates by hand. If you add a minus sign (-) to the start or end of a block, a comment, or a variable expression, the whitespaces before or after that block will be removed
Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#whitespace-control, emphasis, mine
So, for each and every single block in your macro, you have to repeat this operation. To be extra sure, what you could do here is to frame any block in the macro with the minus sign.
Then for the None appearing, this is because you are using an expression delimiter {{ ... }} to append to your array, when you should use a statement delimiter {% ... %} and a do, as pointed in the documentation
If the expression-statement extension is loaded, a tag called do is available that works exactly like the regular variable expression ({{ ... }}); except it doesn’t print anything. This can be used to modify lists
{% do navigation.append('a string') %}
Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#expression-statement
So, your macro should end up looking like:
{%- macro join_them() -%}
{%- set data = [] -%}
{%- for arg in varargs if arg not in ["", None, "None"] -%}
{%- do data.append(arg) -%}
{%- endfor -%}
{{- ' '.join(data) -}}
{%- endmacro -%}
Note that, if you don't have the expression-statement extension loaded, you could also replace the {% do ... %} blocks by this inline-if 'hack':
{{- '' if data.append(arg) -}}

How to calculate the composite's elements and get total of them?

Hi I have a composite that has a QTY field and a TOTAL PRICE field and the table below would calculate and display the subtotal. It works properly when there is only one row of composite, but when I add more items, the subtotal field displays two subtotals instead of one as a whole. I want the subtotal field to display 24 instead of 4 and 20. How can twig solve this implementation? In my SUBTOTAL, I have
{% for item in data.item %}
{% set total_qty = (item.qty)|number_format(2,'.',',') %}
{% set per_price = (item.total)|number_format(2,'.',',') %}
{% set net_cost = (total_qty * per_price )|number_format(2,'.',',') %}
{{ net_cost }}
{% endfor %}
Here is the screenshot to give you better understanding
Don't output the net cost inside the for loop.
First create the sum, then display it after the loop.
Also don't use number_format before the final result.
{% set net_cost = 0 %}
{% for item in data.items %}
{% set net_cost = nest_cost + item.qty * item.total %}
{% endfor %}
{{ net_cost|number_format(2, '.', ',') }}
demo

How in twig to set 2 dimentional array in macros

How in twig to set 2 dimentional array in macros and to run it?
I did :
{{ components.menu_item( "Hostels", 'hostel', {'admin/hostel/index': 'All Hostels'}, {'admin/hostel/active_featured_listings': 'Active Featured Hostels'} ) }}
{% macro menu_item(title, active_admin_link, items_array) %}
title::{{ title }}<br>
items_array::{{ dump(items_array) }}<br>
{% endmacro %} {# menu_item END #}
But only 1st array elemented was outputted
array (size=1) 'admin/hostel/index' => string 'All Hostels' (length=11)
What is rigth way and how make for circle?
Thanks!
From the Twig doc:
["foo", "bar"]: Arrays are defined by a sequence of expressions
separated by a comma (,) and wrapped with squared brackets ([]).
So try surround the input with squared brackets, as follow:
{{ components.menu_item( "Hostels", 'hostel', [{'admin/hostel/index': 'All Hostels'}, {'admin/hostel/active_featured_listings': 'Active Featured Hostels'}] ) }}
Hope this help

Symfony2. Twig: Doesn't work logic function when date variable changes

{% set event_date = event.schedule|date('d-m-y') %}
{% set nowdate = "now"|date('d-m-y') %}
{% if event_date < nowdate %}
view some 1
{% else %}
view some 2
{% endif %}
If change event_date bigger or lower than nowdate, have one result: view some 2.
Why doesn't work?
You are in a string comparison situation. For better approach this, use the U filter as follow:
{% set event_date = event.schedule|date('U') %}
{% set nowdate = "now"|date('U') %}
{% if event_date < nowdate %}
view some 1
{% else %}
view some 2
{% endif %}
{{ event_date }}
Live testing in this fiddle.
Hope this help
You're comparing strings. d-m-y is not a usable format for comparing dates. Try Y-m-d, where the parts are in order of importance.
Even better, you could compare two \DateTime objects instead of strings. I assume event.schedule is one, you just need to pass one for the current date to twig.
In addition to the date filter, Twig defines a date() function which has been designed precisely to compare dates.

Counting the number of elements in array

I am looking to count the number of entries I have in an array in Twig. This is the code I've tried:
{%for nc in notcount%}
{{ nc|length }}
{%endfor%}
This however only produces the length of the string of one of the values in the array.
{{nc}} will produce an output of all the values of the array (there are 2) but I want the output to be just the number 2 (the count) and not all the information in the array.
Just use the length filter on the whole array. It works on more than just strings:
{{ notcount|length }}
This expands on the answer by Denis Bubnov.
I used this to find child values of array elements—namely if there was a anchor field in paragraphs on a Drupal 8 site to build a table of contents.
{% set count = 0 %}
{% for anchor in items %}
{% if anchor.content['#paragraph'].field_anchor_link.0.value %}
{% set count = count + 1 %}
{% endif %}
{% endfor %}
{% if count > 0 %}
--- build the toc here --
{% endif %}
Best practice of getting length is use length filter returns the number of items of a sequence or mapping, or the length of a string. For example: {{ notcount | length }}
But you can calculate count of elements in for loop. For example:
{% set count = 0 %}
{% for nc in notcount %}
{% set count = count + 1 %}
{% endfor %}
{{ count }}
This solution helps if you want to calculate count of elements by condition, for example you have a property name inside object and you want to calculate count of objects with not empty names:
{% set countNotEmpty = 0 %}
{% for nc in notcount if nc.name %}
{% set countNotEmpty = countNotEmpty + 1 %}
{% endfor %}
{{ countNotEmpty }}
Useful links:
length
set
for
{%for nc in notcount%}
{{ loop.index }}
{%endfor%}
loop.index -- The current iteration of the loop.
for reference:https://twig.symfony.com/doc/2.x/tags/for.html

Resources