Manage table with a lot of data twig - symfony

I'm trying to create a table, but as there is a lot of for, I'm getting lost every time.
This is the closest thing I've got at the moment:
Lines should be Bacterie name (nom), Column Mole name (nom) and then a result between them.
On my screen, this is not bad, but I know my synthax won't work because if I add more result, they will not be implemented in the table.
I want the table to be like this :
And when I add results with bactérie and Molecule, table should update in consequence :
<table class = "table">
<caption>{{ session.antibiotique.nom }}</caption>
<tr>
<td></td>
{% for i in 0..((session.antibiotique.resultats|length)|price) -1 %}
<th scope="col">{{ session.antibiotique.resultats[i].molecule.nom}} </th>
{% endfor %}
</tr>
<tr>
<th scope="row">{{ session.antibiotique.resultats[0].bacterie.nom}}</th>
{% for i in 0..((session.antibiotique.resultats|length)|price) -1 %}
<td> {{ session.antibiotique.resultats[i].result}} </td>
{% endfor %}
</tr>
</table>
the price filter on twig return the sqrt value

Related

How to force a page-break on weasyprint?

I wonder if its possible to create a force break that splits the table rows? I think weasyprint does this in a sense but I want to break the rows in to specific counts (e.g 6 rows per page). Is that possible? I tried something like this:
<table>
<tr>
<th>Header1</th>
<th>Header2</th>
</tr>
{% for d in data %}
{% if forloop.counter == 6 %}
<p style="page-break-before: always;"></p>
{% endif %}
<tr>
<td>{{ d.name }}</td>
<td>{{ d.age }}</td>
</tr>
{% endfor %}
</table>
but it just break each row in different pages. Any help would be appreciated.
Try with style attribute on tr element without adding any p element :
<table>
<tr>
<th>Header1</th>
<th>Header2</th>
</tr>
{% for d in data %}
<tr
{% if forloop.counter == 6 %}
style="break-before: page;"
{% endif %}
>
<td>{{ d.name }}</td>
<td>{{ d.age }}</td>
</tr>
{% endfor %}
</table>
Note that page-break-before is deprecated : MDN.
Note also that the result may not be really nice, you may have to add margin-top or something, and also some border at the beginning and end of each block of rows.

Accessing symfony form collection prototype attributes/properties inside twig block

I am trying to setup a custom symfony form collection prototype component of a form. I am referencing the proper documentation
https://symfony.com/doc/3.3/form/form_customization.html#how-to-customize-a-collection-prototype
The form collection is setup using the following
<table class="table table-bordered" data-prototype="{{ form_row(form.quoteItemDeliverables.vars.prototype)|e('html_attr') }}">
<caption>Deliverables</caption>
<tr>
<th>Quantity</th>
<th>Date Required</th>
</tr>
{% for itemDeliverable in form.quoteItemDeliverables %}
<tr>
<td>{{ form_widget(itemDeliverable.quantity) }}</td>
<td>{{ form_widget(itemDeliverable.dateRequired) }}</td>
</tr>
{% endfor %}
</table>
The twig block that is referencing the prototype is setup using the following
{% form_theme form _self %}
{% block _uniflytebundle_quoteitem_quoteItemDeliverables_entry_row %}
<tr>
{#<td>{{ form_widget(form.quoteItemDeliverables.vars.prototype.quantity) }}</td>#}
</tr>
{{ dump(form.children["quoteItemDeliverables"]) }}
{% endblock %}
The dump(); is returning the following error
Key "quoteItemDeliverables" for array with keys "quantity, dateRequired" does not exist.
What am I doing wrong?
If I dump(form); I get the form object displaying the children, the "quoteItemDeliverables" and the "prototype" elements
Can someone please point me in the right direction on how to access the various form properties? Trying to do what was done in the collection form for the prototype. Below being working form collection elements.
<td>{{ form_widget(itemDeliverable.quantity) }}</td>
<td>{{ form_widget(itemDeliverable.dateRequired) }}</td>
I would like the same for the prototype twig block but using something like
form_widget(itemDeliverable.prototype.dateRequired)
does not work. How can I do this?
Thank you in advance for your time and effort invested.
Inside the twig block, form does not refer to the "global" form but to the sub form corresponding to the entry of your collection. That is why the error produced by the dump call indicates that the array has quantity and dateRequired keys but no quoteItemDeliverables.
Thus what you should have is more likely to be something like:
{% block _uniflytebundle_quoteitem_quoteItemDeliverables_entry_row %}
<tr>
<td>{{ form_widget(form.quantity) }}</td>
<td>{{ form_widget(form.dateRequired}}</td>
</tr>
{% endblock %}

How to write twig tags inside TinyMCE

I have an issue with TinyMce combined with Twig,
I'am trying to paste html with twig tags into tinyMce. (using raw html)
here is what i want as a result :
<table>
<thead>
<tr>
<th></th>
{% for period in report.periods %}
<th>
{% set per = "last_" ~ period %}
{{ per | trans({}, "admin") }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for category in report.categories %}
<tr>
<td>
<b>{{ category | trans({}, "admin") }}</b>
</td>
{% for period in report.periods %}
<td>
{{ data[category][period] }}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
This is how it looks like when I paste it into tinyMce and validate my HTML
<p>{% for period in report.periods %} {% endfor %} {% for category in report.categories %} {% for period in report.periods %} {% endfor %} {% endfor %}</p>
<table>
<thead>
<tr>
<th></th><th>{% set per = "last_" ~ period %} {{ per | trans({}, "admin") }} </th>
</tr>
</thead>
<tbody>
<tr>
<td><b>{{ category | trans({}, "admin") }}</b></td>
<td>{{ data[category][period] }}</td>
</tr>
</tbody>
</table>
As you can see, tinyMce moves my twig tags outside the table and break all the logic i wanted to do.
I have tried severals configuration for tinyMce ( cleanup : false ) and also severals versions (3.x, 4.x) directly in the official site.
But it does not work either
Thank you for your help.
You can do some workaround:
<thead>
<tr>
<th></th>
<!--{% for period in report.periods %}-->
<th>
{% set per = "last_" ~ period %}
{{ per | trans({}, "admin") }}
</th>
<!--{% endfor %}-->
</tr>
For TinyMce it is not invalid. Twig render it with some extra empty comments around.
<thead>
<tr>
<th></th>
<!---->
<th>
Result value 1
</th>
<!---->
<th>
Result value 2
</th>
<!---->
</tr>
Use protect option of TinyMCE to disable filtering of TWIG codes:
tinymce.init({
protect: [
/{%(.*)%}/g, // Allow TWIG control codes
/{{(.*)}}/g, // Allow TWIG output codes
/{#(.*)#}/g, // Allow TWIG comment codes
]
})
This looks complex to me, as to put something between </td> and <td> will result as invalid HTML.
TinyMCE is a WYSIWYG HTML editor, so it will try to interpret your HTML to render it as it will result; and this is at this step that your original HTML is broken. Just try, in any browser, to render the following code:
<table border=1>
<tr>
<td>test</td>
hello
<td>test</td>
world
<td>test</td>
</tr>
</table>
You will get something like:
Code out of the table scope has been placed above, this behaviour really looks like the HTML you get while validating your TinyMCE field.
As Twig files are just templates and not final documents, there is no logic to import them on a WYSIWYG editor, as invalid html just can't be rendered. I would recommand you to replace TinyMCE by codemirror used in jinja mode to get a proper Twig editor.
I had exactly the same problem, TinyMCE rearranging Twig tags.
I'm using v4.1 and only solution which is working for Twig tags in table is adding HTML comment around Twig tags so your code would be something like this
<thead>
<tr>
<th></th>
<!-- {% for period in report.periods %} -->
<th>
<!-- {% set per = "last_" ~ period %} -->
<!-- {{ per | trans({}, "admin") }} -->
</th>
<!-- {% endfor %} -->
</tr>
I used <!--TWIG: { my twig tags} :TWIG--> then remove comments with regexp on save.
AFAIK there is no config option which would prevent rearranging Twig tags in table outside of cell <td>

Editing Twig templates in CKeditor

I'm trying to allow admin users to edit email templates. These templates are stored in the DB as Twig ones. So the variables in them are set as {{ purchase.number }} and there are loops like
{% if cart['shipping'] %}
{% for line in cart['shipping'] %}
<tr>
<td colspan="7">Shipping ({{ line['text'] }})</td>
<td>US${{ line['money'] }}</td>
</tr>
{% endfor %}
{% endif %}
Below is one of the templates where I can reproduce this issue:
<html>
<body>
<h3>Order #{{ purchase.number }} was cancelled</h3>
<p>Order content:</p>
<table>
<tr>
<th>Line</th>
<th>Item #</th>
<th>Product Name</th>
<th>Shipping</th>
<th>UOM</th>
<th>Unit Price</th>
<th>Quantity</th>
<th>Subtotal</th>
</tr>
{% for line in cart['cart'] %}
<tr>
<td>{{ line['LineNo'] }}</td>
<td>{{ line['ItemNo'] }}</td>
<td>{{ line['ProductName'] }}</td>
<td>{{ line['Shipping'] }}</td>
<td>{{ line['UOM'] }}</td>
<td>US${{ line['UnitPrice'] }}</td>
<td>{{ line['Quantity'] }}</td>
<td>US${{ line['Subtotal'] }}</td>
</tr>
{% endfor %}
{% if cart['shipping'] %}
{% for line in cart['shipping'] %}
<tr>
<td colspan="7">Shipping ({{ line['text'] }})</td>
<td>US${{ line['money'] }}</td>
</tr>
{% endfor %}
{% endif %}
<tr>
<td colspan="7"><b>Order Item Total:</b></td>
<td>US${{ cart['total'] }}</td>
</tr>
</table>
</body>
</html>
When I just open a page with CKEditor textarea with this template in it, I do no changes to the template and just click on "Source" button and here is how the above mentioned template looks after the click:
<h3>Order #{{ purchase.number }} was cancelled</h3>
<p>Order content:</p>
{% for line in cart['cart'] %} {% endfor %} {% if cart['shipping'] %} {% for line in cart['shipping'] %} {% endfor %} {% endif %}
<table>
<tbody>
<tr>
<th>Line</th>
<th>Item #</th>
<th>Product Name</th>
<th>Shipping</th>
<th>UOM</th>
<th>Unit Price</th>
<th>Quantity</th>
<th>Subtotal</th>
</tr>
<tr>
<td>{{ line['LineNo'] }}</td>
<td>{{ line['ItemNo'] }}</td>
<td>{{ line['ProductName'] }}</td>
<td>{{ line['Shipping'] }}</td>
<td>{{ line['UOM'] }}</td>
<td>US${{ line['UnitPrice'] }}</td>
<td>{{ line['Quantity'] }}</td>
<td>US${{ line['Subtotal'] }}</td>
</tr>
<tr>
<td colspan="7">Shipping ({{ line['text'] }})</td>
<td>US${{ line['money'] }}</td>
</tr>
<tr>
<td colspan="7"><b>Order Item Total:</b></td>
<td>US${{ cart['total'] }}</td>
</tr>
</tbody>
</table>
Notice that not only single quote changes to html code, but the main thing is that loops are moved, so it used to be:
{% if cart['shipping'] %}
{% for line in cart['shipping'] %}
<tr>
but becomes:
{% for line in cart['cart'] %} {% endfor %} {% if cart['shipping'] %} {% for line in cart['shipping'] %} {% endfor %} {% endif %}
Why does CKEditor change the source if these entities are NOT html and I don't do any changes, I don't even focus on the field.
I tried using these CKEditor config options:
CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR;
CKEDITOR.config.entities = false;
CKEDITOR.config.forcePasteAsPlainText = false; // default so content won't be manipulated on load
CKEDITOR.config.basicEntities = true;
CKEDITOR.config.entities = true;
CKEDITOR.config.entities_latin = false;
CKEDITOR.config.entities_greek = false;
CKEDITOR.config.entities_processNumerical = false;
CKEDITOR.config.fillEmptyBlocks = function (element) {
return true; // DON'T DO ANYTHING!!!!!
};
But I still experience this. Can anyone advise on the config option or any other workaround, except for not using WYSIWYG. I tried to convince users to edit html/twig, but the just want WYSIWYG. Thanks
One possible workaround for me, was to add the Twig blocks to config.protectedSource:
CKEDITOR.config.protectedSource.push(/\{%\s.+\s%\}/g);
They will be ignored in the WYSIWYG editor, but will still be visible in the source code view.
Additionally you can install the plugin Show protected and there's still a visible hint.
working code is :
CKEDITOR.config.protectedSource.push(/{{[\s\S]?}}/g);
CKEDITOR.config.protectedSource.push(/{\%[\s\S]?%}/g);
CKEDITOR.config.protectedSource.push(/{#[\s\S]*?#}/g);
because we need allow {{ and {% tags for twig
CKEDITOR.config.protectedSource = [
/\{\{[\s\S]*?\}\}/g,
/\{\%[\s\S]*?%\}/g,
/\{\#[\s\S]*?#\}/g,
];
This is why I love Stack Overflow - no matter what you want to ask, someone's probably already asked it! In this case, the answers were close, but for me, adding them as protected source was no good - I wanted to create the twig templates in the string as we use them for Email Templates within our CRM. So, what I did was leave CKEditor to do its thing and then handle it before the template was saved (in our case into the DB, but it could as well be to file).
The function I added is pasted below - feel free to use & abuse as you wish.
This is from our custom Symfony controller onBeforePersist a hook that's called before the entity is persisted... Hopefully its all self explanatory from the code.
Note, the Regex may be a bit dodgy, but appears to work, I'm no Regex expert, so please feel free to suggest a more concise expression.
/**
* Before we persist the data, we need to clean up any twig tags in there as the editor encodes html entities...
*
* #param Request $request
* #param $form
* #param EmailTemplates $entity
*/
public function onBeforePersist(Request $request, $form, $entity)
{
$template = $entity->getView();
$re = '/\{(\{|%)([^{}]|(?R))*(\}|%)\}/';
preg_match_all($re, $template, $matches, PREG_SET_ORDER, 0);
// We only want the first element of each match - I don't like closures as a rule on readability grounds, but this is small enough to be ok.
array_walk($matches,function(&$value) {
if (array($value)) {
$value = $value[0];
}
});
// Now do a replace on them
foreach ($matches as $match) {
$decoded = html_entity_decode($match,ENT_QUOTES);
if ($match != $decoded) {
// Only replace if we have actually changed the string
$template = str_replace($match, $decoded, $template);
}
}
// Update the View...
$entity->setView($template);
}
Similar question CKEditor is escaping html elements
Quick question, the above is a list of config options you have tried one at a time? Having both like this
CKEDITOR.config.entities = false;
CKEDITOR.config.entities = true;
sets entities to true, which is not what you want as it forces html entities in output.
By the way, the other answers are OK but if you have more than one Twig block in the same sentence, are not.
So I definetly recommend to use this Regex instead that works with multiple Twig blocks too:
CKEDITOR.config.protectedSource.push(/\{\{[\s\S]*?\}\}/g);
CKEDITOR.config.protectedSource.push(/\{\%[\s\S]*?%\}/g);

Tables and forms in Twig

I have a table-form which I implemented this way:
<tr>
<td>Start Date:</td>
<td>{{ form_widget(form.start_date) }}</td>
</tr>
<tr>
<td>Previous Plan:</td>
<td>{{ form_widget(form.prev_plan) }}</td>
</tr>
Is there a way to make this using the ready theme form_table_layout.html.twig or at all in some more flexible and elegant way?
I tried this:
{% form_theme form 'form_table_layout.html.twig' %}
{{ form_errors(form) }}
{% for field in form %}
{{ form_row(field) }}
{% endfor %}
but it puts its own names in the left part of the table which are not the names I want. (For example instead of "Previous Plan: " in this way I got "Prev plan")
You can define your own labels when defining the form. Something like:
->add('prev_plan', 'text',array(
'label' => 'Previous Plan'
))
(I don't know the field type for prev_plan, I used 'text' but if it is a different field type just change that)

Resources