I have the following controller :
public function indexAction(Request $request)
{
if (!$request->isXmlHttpRequest())
{
$this->denyAccessUnlessGranted('ROLE_ESP_NAC', null, 'Imposible acceder a este recurso !!');
$repositoryRiesgos = $this->getDoctrine()->getRepository('AppBundle:Riesgo');
$listado = $repositoryRiesgos->findAll(); //findByPages($request->get('page', 1));
return $this->render('AppBundle:CodifRiesgos:index.html.twig', array('riesgos' => $listado));
} else
{
try
{
$this->denyAccessUnlessGranted('ROLE_ESP_NAC', null, 'Imposible acceder a este recurso !!');
} catch (AccessDeniedException $denyExc)
{
return new Response($denyExc->getMessage(), 403);
}
$repositoryRiesgos = $this->getDoctrine()->getRepository('AppBundle:Riesgo');
$listado = $repositoryRiesgos->findAll();
return $this->render('AppBundle:CodifRiesgos:tablaRiesgos.html.twig', array('riesgos' => $listado));
}
}
Even in the controller I practically repeated the code for both the request via AJAX and the normal one.
Now the templateindex.html.twig
is as follows:
{% extends "::base.html.twig" %}
{% block title %} PAMI - Codificadores {% endblock %}
{% block principal %}
<br/>
<div class="breadcrumb">
<a href="{{ path('app_homepage') }}">Inicio<span class="glyphicon glyphicon-chevron-right"></a>
Riesgos<a class="lnkRecargarRiesgos" href="{{ path('riesgos_listado') }}"> <span class="glyphicon glyphicon-refresh"></span></a>
</div>
<div id="tablaDatos">
<table id="tablaRiesgos" class="table table-condensed table-hover table-responsive">
<thead>
{% if app.user and is_granted('ROLE_ESP_NAC') %}
<tr>
<th colspan="5"><a id="lnkRegistrarRiesgo" href="{{ path('riesgos_registrar_nuevo') }}"><span class="glyphicon glyphicon-plus"></span> Nuevo</a></th>
</tr>
{% endif %}
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>Alto</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
</thead>
<tbody>
{% for riesgo in riesgos%}
<tr id="filaRiesgo_{{ riesgo.id }}">
<td>{{ riesgo.nombre }}</td>
<td>{{ riesgo.descripcion }}</td>
<td>
{% if riesgo.calificaComoAltoRiesgo %}
<span class="glyphicon glyphicon-hand-up"></span>
{% endif %}
</td>
<td><a class="lnkEditarRiesgo" href="{{ path('riesgos_editar', {'id':riesgo.id}) }}"><span class="glyphicon glyphicon-edit"></span></a></td>
<td><a class="lnkEliminarRiesgo" href="{{ path('riesgos_eliminar', {'id':riesgo.id}) }}"><span class="glyphicon glyphicon-remove"></span></a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
$(document).ready(function(){
$('a.lnkRecargarRiesgos').on('click', function(e) {
e.preventDefault();
var url = $(this).attr('href');
$.ajax({
'datatypes': 'html',
'type': 'GET',
'url': url,
beforeSend: function() {
$('#indicador').addClass('cargando-satisfactorio').fadeIn('fast');
}
}).done(function(data) {
$('#tablaDatos').html(data);
}).fail(function(jqXHR) {
$('#indicador').removeClass('cargando-satisfactorio').addClass('cargando-error').html(jqXHR.responseText);
}).always(function() {
$('#indicador').fadeOut('slow', function() {
$(this).removeClass('cargando-error').html("<span class='glyphicon glyphicon-time'></span> Cargando...");
});
});
});
$('#tablaRiesgos tbody tr a.lnkEliminarRiesgo').on('click', function(e) {
e.preventDefault();
var idRiesgo = $(this).attr('id');
var url=$(this).attr('href');
var trPadre=$(this).parents('tr');
$.ajax({
'datatypes': 'html',
'type': 'GET',
'url': url,
beforeSend: function() {
$('#indicador').addClass('cargando-satisfactorio').fadeIn('fast');
}
}).done(function(data) {
$(trPadre).remove();
$('#indicador').html(data);
}).fail(function(jqXHR) {
$('#indicador').removeClass('cargando-satisfactorio').addClass('cargando-error').html(jqXHR.responseText);
}).always(function() {
$('#indicador').fadeOut(4900, function() {
$(this).removeClass('cargando-error').html("<span class='glyphicon glyphicon-time'></span> Cargando...");
});
});
});
});
</script>
{% endblock %}
The problem is the following:
- When the template is initially loaded, the event
onclick
associated witha.lnkEliminarRiesgo
works correctly. - Then, clicking on the
a.lnkRecargarRiesgos
, I reload the same updated information (via AJAX) indiv#tablaDatos
. - But now, because the was rebuilt
a.lnkEliminarRiesgo
, the event that was originally attached to is not fired.on('click',...
. Instead, thehref
because it didn't run link is followede.preventDefault()
.
I want the on click event to continue to work the same as it did at the beginning.
I don't know if my approach to working with templates in Symfony2 is wrong or I'm missing something or I'm not approaching the use of asynchronous calls well, or the way I'm including the JavaScript.
I recommend linking it like this:
In the previous answers the bind is made to
body
, if thebody
change can break the bind or even generate something known as "double firing"... that's why it is recommended to make the link to the document. Part of the event, the callbackxhr
andsettings
, which can help you in debugging, are also instantiated.You should also check if the function requires any plugging to follow this trend or you will have to reload the plugging N amounts of times and make the unbind broken.
At the time of binding the events, I started the filter in a tag
div
withid='vistas'
, which for this specific application will be in that element where all the views of the AJAX calls are loaded, so it will not disappear from the page. And in the case of the delete functionality, it is always done on a table with id='tablaDatos'$('#vistas').find('#tablaDatos tbody tr a.lnkEliminarRegistro').on('click', function(e) { ... }
This way the event binding
click
on classful tags will always be maintained<a>
, for example:lnkEliminarRegistro
.That way I use the implementation for the delete functionality of all the tables of the views loaded inside
<div class='vistas'></div>
One of the correct ways to do it is
This way, you keep the event bound to the body element (which, in theory, won't vary in your app's DOM) and do filtering on the selector
#tablaRiesgos tbody tr a.lnkEliminarRiesgo
, so you don't have to continually bind an eventclick
to newly created elements.