Symfony2, get value of input field with Twig - symfony

I want to get the value of an input field from my template twig with twig not with javascript.
My input field hasn't a form, it is a hidden input.
{% block body -%}
<input type="hidden" name="id_client" id="id_client" value="123"/>
...
{% endblock %}
I want to do this:
{{ path('client_view',{"id": value_Of_Hidden_Input}) }}
How can I get value_Of_Hidden_Input
EDIT:
My requirement:
I have a list of customers and I have for each customer a button to show details of customer "Modifier coordonnées".
I want on clicked one customer a function AJAX will executing the action showAction
This is my code:
{% block body -%}
<div class="tab-client">
<table id="mytable" class="table table-bordred table-striped" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>Raison Sociale</th>
<th>Identifiant</th>
<th>M. de passe</th>
<th>Solde actuel</th>
<th class="text-center sty-td-action">Action</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr>
<td>{{ entity.raisonSociale}} </td>
<td>{{ entity.login }}</td>
<td>{{ entity.password }}</td>
<td>{{ entity.soldeSMS }}</td>
<td>
<a class="modifier-client" id="modif_coordonnee"><span class="glyphicon glyphicon1">Modifier coordonnées</span></a>
<span class="glyphicon glyphicon2">Voir Historique</span>
<span class="glyphicon glyphicon3">Ajout transaction</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div><!--tab-client-->
{% endblock %}
{% block javascripts %}
<script>
$("#modif_coordonnee").click(function() {
$.ajax({
//On lui indique le type d'envoie des informations
type: 'POST',
//On lui indique le chemin de la fonction
url: '{{ path('client_show',{"id": value_of_id_client}) }}',
//On lui donne la valeur du choix qu'on a fait, et id est la variable qui va contenir notre valeur, nous la retrouvons dans notre controller
//Enfin nous lui disons de remplir notre formulaire avec le resultat
success: function(response)
{
......
}
}
)});
</script>
{% endblock %}
My problem is how can determined value_of_id_client?

try this .
{{ path('client_view',{"id": form.name_field_hidden.vars.value}) }}
Have more information on http://symfony.com/doc/current/reference/forms/twig_reference.html

First of all: An id must be unique throughout the whole document. If you have multiple targets use the class-attribute instead. I also added the current url including the corresponding id to each entity in your loop, using the HTML5 data-attribute:
{% for entity in entities %}
[…]
<a class="modifier-client handler" data-href="{{ path('client_show',{ 'id': entity.id }) }}">
<span class="glyphicon glyphicon1">Modifier coordonnées</span>
</a>
[…]
{% endfor %}
In your JavaScript part, you have to change the selector and retrieve the url of the currently clicked element:
$('.handler').click(function() {
var href = $(this).data('href');
$.ajax({
[…]
url: href,
[…]
));
});

You need to use FOSJsRoutingBundle to generate a proper Symfony path that takes in an argument and places it in the correct portion of the URL (depending on your routes, your variable portion may be somewhere in the middle of the URI!)
You must follow all the installation instructions for the bundle, and make sure you expose the route in question.
Then you pull the value into the Routing.generate function by passing the value retrieved by jQuery:
url: Routing.generate('client_show', {id: $('#id_client').val()}),

You can't do this that way, try(js):
{{path('client_view')}}/+$("#id_client").val()

I think the correct way to handle this is in the controller.
When you post the form, take that hidden value and inject it into your template.
Pull id_client from the Request object.
$this->render('TEMPLATE', array('client_id'=>$request->query->get('id_client'));
Then in your template, you can use the client_id variable.

Related

symfony 5 get data of many to many relation

how i get user_id of table : user_evento ?
i need compare who user join on table : evento,
enter image description here
controller
public function evento_detalle(Evento $evento){
if(!$evento){
return $this->redirectToRout('ver_eventos');
}
$salas = $this->getDoctrine()->getRepository(Sala::class)->findBy([],['id' => 'desc']);
$users = $this->getDoctrine()->getRepository(User::class) ->findBy([],['id' => 'ASC']);
return $this->render('evento/ver-evento.html.twig',[
'eventos' =>$evento,
'users' =>$users,
'salas' =>$salas
]);
}
twig
{% for user in users %}
{% if user.id == eventos.getUsers.evento %}
<tr>
<td>
{{ user.nombre }}
</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
{%endif%}
{% endfor %}
If you are trying to list Users associated with a particular Evento you should find them all in the collection returned by the Evento::getUsers() method, provided you have followed best practices for Symfony.
{% for user in eventos.getUsers %}
...
{{ user.nombre }}
...
{% endfor %}

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 display large table in twig with symfony?

I have an entity with 3,000 records, and when I render my index.html.twig that information takes about 35 seconds to display the datatable.
My question here is, how can I perform the rendering of the table?
I have looked around but no luck!
Please help me.
Thanks,
Controller
public function indexAction()
{
if ($this->getUser() == NULL){
return $this->redirect($this->generateUrl('login_route'));
}
$em = $this->getDoctrine()->getManager();
$session = $this->get('session');
$id_empresaa = $session->get('idempresa');
$session->set('viewProd', 1);
$entities = $em->getRepository('NivalInventarioBundle:InProducto')->findBy(array(
'idEmpresaa' => $id_empresaa
));
return $this->render('NivalInventarioBundle:InProducto:index.html.twig', array(
'entities' => $entities,
));
}
Twig:
{% extends 'NivalInventarioBundle:Default:index.html.twig' %}
{% block content %}
{% block inventario_menu %}
{{ parent() }}
{% endblock %}
<h3>Productos</h3>
<div class="row" style = margin-bottom:55px;">
<div class="col-md-12">
<table id="ftable" class="table table-condensed table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>Código</th>
<th>Nombre</th>
<th>Unidad</th>
<th>Costo</th>
<th>Sub-Linea</th>
<th>Linea</th>
<th>Invent.</th>
<th>Factura</th>
<th>Activo</th>
<th width="60px">Opción</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr>
<td>{{ entity.idProducto }}</td>
<td>{{ entity.nombre }}</td>
<td>{{ entity.unidadMedida.nombre }}</td>
<td class="text-right">{{ entity.costoPromedio|number_format(4) }}</td>
<td>{{ entity.subLinea.nombre }}</td>
<td>{{ entity.subLinea.linea.nombre }}</td>
<td>
{% if entity.inventariable == 0 %}
No
{% elseif entity.inventariable == 1 %}
Sí
{% endif %}
</td>
<td>
{% if entity.facturable == 0 %}
No
{% elseif entity.facturable == 1 %}
Sí
{% endif %}
</td>
<td>
{% if entity.activo == 0 %}
No
{% elseif entity.activo == 1 %}
Sí
{% endif %}
</td>
<td class = "actions">
<a href="{{ path('inproducto_show', { 'id': entity.idProducto }) }}"
class = "btn btn-sm btn-info glyphicon glyphicon-search" data-toggle="tooltip" title="Ver"></a>
{% if app.user.nivel > 60 %}
<a href="{{ path('inproducto_edit', { 'id': entity.idProducto }) }}"
class = "btn btn-sm btn-primary glyphicon glyphicon-edit" data-toggle="tooltip" title="Editar"></a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if app.user.nivel > 30 %}
<div class="col-md-12">
<a href="{{ path('inproducto_new') }}"
class = "btn btn-success glyphicon glyphicon-plus" data-toggle="tooltip" title="Nuevo"></a>
</div>
{% endif %}
</div>
{% endblock %}
Javascript:
<script>
$(document).ready(function() {
$('#ftable').DataTable({
stateSave: true,
language: {
"emptyTable": "No hay datos disponibles en la tabla",
"info": "Mostrando _START_ hasta _END_ de _TOTAL_ registros",
"infoEmpty": "Mostrando 0 hasta 0 de 0 registros",
"lengthMenu": "Mostrar _MENU_ registros",
"search": "Buscar:",
"loadingRecords": "Cargando...",
"processing": "Procesando...",
"paginate": {
"first": "Primero",
"last": "Ultimo",
"next": "Siguiente",
"previous": "Anterior"
},
"infoFiltered": "(filtrados de _MAX_ registros)"
}
});
$('.selectpicker').selectpicker({
size: 8
});
$('.datepicker').datepicker({
format: 'dd-mm-yyyy',
autoclose: true
})
} );
</script>
Loading an HTML table with 3000 records is heavy, and doing that with a full framework, ORM and templating engine is even heavier.
The best approach for this situation is to load the records dynamically on the table, querying only for what you're displaying and doing a real pagination. You can do it in two ways:
Option 1
You can follow the DataTables documentation on how to do it and then implement the JS calls, the controller actions to grab the data and the HTML templates. That's not hard if you know your way around Symfony, but it can be a lot of work.
Option 2
Use DatatablesBundle and let it handle everything for you. It's pretty straightforward and they have a good documentation and even an example repository.
Despite of table with 3000 records is heavy (as mentioned before), 35 seconds is extremely much for the table. Reasonable time should be less than 1-2 second because Twig is pretty fast engine.
Found <td>{{ entity.unidadMedida.nombre }}</td> in your template. Probably you haven't defined EAGER fetch in your entity, so it calls SQL query time when it request unidadMedida field.
Open your Symfony profiler page (in dev mode it's usually /_profiler/) and check how many Doctrine queries you have. Of course if there are thousand of database requests loading time will be inadequate.
Here is sample code (working) that I use with Paginator:
$pagination = $paginator->paginate(
$query, /* query NOT result */
$request->query->getInt('page', 1)/*page number*/,
10/*limit per page*/
);
The last parameter 10 sets the number of items per page. I believe this will be a good solution for you (I mean using paginator).
I implemented KnpPaginatorBundle, it works very good, I recomended it: https://github.com/KnpLabs/KnpPaginatorBundle

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);

Resources