Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Mejor práctica para pasar valores a una función Ajax

3 de enero de 2014

Hola,

Tengo un formulario con varios tag anchor a los cuales tengo asociados el evento click de AJAX. Hasta ahora la forma que he usado para pasar valores que me interesan a la función creada en AJAX ha sido extrayendo el parámetro del id del anchor, ya que previamente lo había insertado en el mismo:

Por ejemplo: <a id="abcdefg1235" class="elemento" >Ejemplo</a>, siendo 1235 el valor que quiero pasar a un controlador de symfony.

$('.elemento').click(function(e) {
    var data = {
        numero_respuesta: ($(this).attr('id')).slice(8)
    };
 
    ...
}

Ahora me enfrento al caso en el que no puedo realizar de esta forma el paso de parámetros. Sabiendo que el parámetro que me interesa obtener se encuentra en la URL de la página que muestra el anchor, me gustaría saber si existe alguna otra forma de pasar al data del evento click de dicho anchor (descartando el uso del atributo href del anchor) además de si es buena práctica o no hacerlo de la forma en la que lo venía haciendo.

Un saludo


Respuestas

#1

No se si lo he entendido bien eso de sin usar href. Cuando creas la vista ¿no puedes ponerlo?

<a class="elemento" href="./noticia/13">Ejemplo</a>
$('.elemento').click(function(e) {
    e.preventDefault(e);
    $url = $(this).attr('href');
 
    $.get($url, function(data){
        console.log(data);
    });
})

Otra manera:

<a class="elemento" data-id="13">Ejemplo</a>
$('.elemento').click(function(e) {
    e.preventDefault(e);
    $url = 'www.prueba.com/noticias';
 
    $.get($url,{ id: $(this).attr('data-id')}, function(data){
        console.log(data);
    });
})

otra manera: en una página cuya URL sea www.prueba.com/noticias/13

$('.elemento').click(function(e) {
    e.preventDefault(e);
 
    var pathname = window.location.pathname;   
    pathname =pathname.split('/');
    var id = pathname[2];
 
    $.get($url,{ id: id}, function(data){
        console.log(data);
    });
})

Pienso que la forma más correcta es la de href, así si el usuario tiene desactivado JavaScript puedes hacer que siga funcionando... si es que te vale la pena

@AlbertoVioque

3 enero 2014, 18:42
#2

A ver si soy capaz de explicarme. Tengo una vista principal llamada recurso.html.twig, dentro de la cual renderizo otra vista a través de:

{{ render(
    controller('ExtranetBundle:Default:SelectRecursos', { 'instruccion': instruccion }),
    { 'strategy': 'inline' }
) }}

Este controlador lo que hace es cargar un form a la vista SelectRecursos.html.twig que en definitiva se trata de tres <select> encadenados a los cuales se añaden a cada uno tres etiquetas <a> como botones para seleccionar "Nuevo", "Editar" y "Eliminar".

Si el usuario pulsa el botón "Nuevo" se le redirige mediante el atributo href a una vista con otro formulario, pasando con este atributo un parámetro id necesario para crear el formulario.

Mi problema viene cuando el usuario quiere pulsar el botón "Editar". En este caso necesito para crear un formulario adecuado, además del parámetro que paso con href, otro parámetro que está relacionado con el valor actualmente seleccionado en el <select>.

En resumen, necesito redirigir al usuario a un formulario para cuya creación se requieren dos valores: uno que viene predefinido y que se conoce antes de que el usuario interaccione con la vista y otro que depende del valor elegido en el <select> por el usuario.

Si ven algún error en mi razonamiento digánmelo: Si uso AJAX para el evento click del botón "Editar" podré extraer tanto el valor actual del <select> como el atributo que tenía en href.

  • Evento click del botón "Editar":
var data = {
    recurso1_id: $("#select_recurso_recurso1").val(),
    instruccion_id: $(".botonEditar").attr('href');
};
  • Controlador asociado mediante @Routing al evento click: aquí trato los datos para pasar un array con la información que requiero para crear la página en la que se encuentra el formulario.

  • Vista asociada mediante @Template al evento click: aquí llegan los datos referidos anteriormente, si bien esta vista no puede mostrarse en otra página distinta (que es lo que pretendo), ya que nos encontramos en una comunicación asíncrona.

  • Finalmente llegamos al .success{} de la función AJAX, en donde data sería la vista del punto anterior.

¿Como redirijo esta información con la vista del formulario a otra ruta?

@Jorge_Gante

4 enero 2014, 11:10
#3

@Jorge_Gante, me gustaría ayudarte pero no acabo de entender cuál es exactamente el problema que planteas. Sigo tu razonamiento, pero me pierdo en tu última pregunta:

¿Como redirijo esta información con la vista del formulario a otra ruta?

No entiendo por qué quieres redirigir el formulario renderizado a otra ruta. Si el controlador te entrega la plantilla renderizada, ya la puedes mostrar en tu página. Y si lo que quieres es mostrar esa plantilla en otra página, ¿para qué utilizas AJAX y no simplemente un enlace a otra página?

@javiereguiluz

4 enero 2014, 15:51
#4

Uso AJAX porque no sé otra forma de conocer el valor del <select> que ha escogido el usuario. El controlador me entrega la plantilla renderizada en data, pero al hacerse todo sin contar con el servidor, la página se queda en el mismo sitio (url) que estaba.

Entonces lo que quiero saber es como puedo mostrar la plantilla renderizada (la cual tengo almacenada en data), una vez estamos en la parte del .success{} y si es posible que desde ese mismo controlador se pueda procesar el formulario contenido en la plantilla renderizada mencionada cuando el usuario "edite" su contenido.

@Jorge_Gante

4 enero 2014, 18:01
#5

Yo tampoco me aclaro pero... ¿por qué no intentas modificar el atributo href del enlace añadiéndole el valor del <select> y creando una ruta para ello?

$('.elemento').click(function(e) {
    var url = $(this).attr('href');
 
    url = url + '/opcion/'+$('#select').find('option:selected').val();
 
    $(this).attr('href', url);
})

También puedes hacer que no se mueva de la pantalla, o sea una vez llamas por AJAX y te devuelve el contenido de la plantilla, vacías el contenedor de la pantalla y metes lo devuelto en el data:

<div id="contenedor">
    <form>
        <div id="fila-1">
            <select name="" class="opcion">...</select>
            <a href="" class="editar">Editar</a>
        </div>
    </form>
</div>

Con AJAX:

$('.editar').click(function(e) {
    e.preventDefault(e);
 
    var url = $(this).attr('href');
    var opcion = $(this).parent().find('.opcion').find('option:selected').val();
 
    $.get(url,{ id: opcion}, function(data){
        $('#contenedor').html(data);
    });
});

A ver si es eso lo que buscas.

Saludos!!

@AlbertoVioque

4 enero 2014, 19:35
#6

Gracias por contestar @AlbertoVioque. Aunque comencé preguntando por lo que me has contestado, los parámetros los obtengo de la siguiente forma:

$("#editarRecurso1").click(function() {
 
    var data = {
        instruccion_id: "{{instruccion.id}}",
        recurso1_id: $("#select_recurso_recurso1").val()
    };
}

Donde

  • #editarRecurso1 sería el botón <a> que pincha el usuario para editar un valor.
  • {{instruccion.id}} el parámetro que ya conocía y tenía en la URL
  • $("#select_recurso_recurso1").val() el valor actual del <select> que el usuario ha escogido

La pregunta ha derivado en que una vez tengo todos esos datos accesibles desde el controlador y devolviendo los siguientes valores:

return array (
    'formulario'  => $formulario->createView(),
    'instruccion' => $instruccion,
    // resto de valores ...
);

a una plantilla @Template("AcmeBundle:Default:form.html.twig") especificada en el controlador, y sabiendo que:

  • Esta plantilla renderizada se devuelve al parámetro data de la parte .success {} de la función AJAX $("#editarRecurso1").click(function()) que puse al principio.
  • Teniendo en cuenta que al ser una función que se ejecuta de forma asíncrona, mediando únicamente una comunicación cliente-navegador sin contar con el servidor (motivo por el que puedo mostrar esa plantilla renderizada en un <div>, o en cualquier elemento de la página actual de forma estática al usuario, si bien lo que me interesa es mostrarla en una página con su ruta aparte, ya especificada en el @Route() del controlador)

¿Qué debo poner en el .success{} para que la plantilla renderizada que tengo en data se muestre en la pantalla?

@Jorge_Gante

5 enero 2014, 9:00