martes, 4 de junio de 2013

Ajax: envío de datos (uso de ajax sin la librería jquery)

Bueno este es otro ejemplo de Ajax, en este caso no voy a utilizar la librería jquery como en los ejemplos anteriores si no que voy a realizar la conexión directa utilizando  XMLHttpRequest.
Objetivo del ejercicio es un formulario de envió de comentarios. (Basada en un comentario  hecho por  Alexa.) El comentario se envia por medio de Ajax para no refrescar la página, y se va a insertar en una base de datos, la respuesta del servidor va a ser una leyenda "su comentario ha sido enviado conéxito."

ok se verá así:

Antes de oprimir el botón de enviar

Al oprimir el botón enviar, leyenda de resultado

Bueno voy a utilizar 2 archivos el html que va a contener el formulario y las funciones de Ajax (js)  y el archivo php que va a contener la conexión con la base de datos y va a enviar la respuesta ok.

Veamos primero el archivo html el código sería el siguiente y abajo explicaré un poco. ok:


<HTML>
<HEAD>
 <title>AJAX sin jquery</title>
<script type="text/javascript">
function conectar() {
  // Obtener la instancia del objeto XMLHttpRequest
  if(window.XMLHttpRequest) {
    conexion = new XMLHttpRequest();
  }
  else if(window.ActiveXObject) {
    conexion = new ActiveXObject("Microsoft.XMLHTTP");
  }

  var comentarios=encodeURIComponent(document.getElementById("comentarios").value);

  // Preparar la funcion de respuesta
  conexion.onreadystatechange = respuesta;

  // Realizar peticion HTTP
  conexion.open('POST', 'ejemplo2.php');
  conexion.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  conexion.send("comentarios="+comentarios+"&nocache="+ Math.random());
}

function respuesta() {
  if(conexion.readyState == 4) {
    if(conexion.status == 200) {
      document.getElementById("respuesta").innerHTML = conexion.responseText;
      window.setTimeout(limpiar,5000)
    }
  }
}
  
function limpiar(){
  var d = document.getElementById("respuesta");
  while (d.hasChildNodes())
        d.removeChild(d.firstChild);
}

</script>
</HEAD>
<BODY>

  <table>
         <tr> <td colspan="2">DEJE SUS COMENTARIOS</td></tr>
         <tr><td><textarea rows="4" cols="50" id="comentarios"></textarea></td></tr>
         <tr><td><button onclick="conectar();">Enviar</button></td></tr>
  </table>
  <div id="respuesta"></div>
  
</BODY>
</HTML>


Bueno dejenme les explico un poquito el código:
De elementos tenemos muy pocos como pueden ver en una tabla tenemos un objeto textarea que es donde los usuarios dejarán sus comentarios a este textarea le ponemos el id="comentarios" muy importante por que lo vamos a mandar llamar por medio de este atributo. Tenemos tambien un boton al que en su propiedad onclick vamos a mandar llamar la función conectar(); . Y por último pero muy importante tenemos un div con el id="respuesta" este es muy importante por que en este div es donde se va a cargar la respuesta a la peticion Ajax ok.

En la sección header tenemos nuestro script js , dentro de el tenemos 3 funciones: conectar() , respuesta() y limpiar():

Conectar():
En conectar tenemos primero un if esto es por que dependiendo del navegador es como se obtiene la instancia XMLHttpRequest que es la clave para realizar la conexión con el servidor.
Hoy en día los navegadores (más conocidos, google chrome, firefox, ie 7 Y 8 , safari) ya tienen de forma nativa este objeto por lo que se puede llamar por medio de window.XMLHttpRequest pero aún hay personitas que siguen utilizando ie 6 y ahí es que se tienen que usar el window.ActiveXObject.

ahí es entonces donde vamos a tener nuestra variable conexión que va a ser igual a la instancia del objeto XMLHttpRequest (según lo anterior ok)

Despues declaramos tambien una variable comentarios que va ser igual al objeto textarea (por eso no hay que olvidar el id ) esta variable va a contener el mensaje que el usuario haya escrito en este objeto.
pueden ver que tiene encodeURIComponent() esta función es muy importante por que evita que marque errores en algunos caracteres a la hora de enviar el dato.

ahora conexion.onreadystatechange = respuesta. Aqui le estamos indicando que cuando nuestra conexion este en estado completo va a llamar a la funcion respuesta(la explicaremos mas adelante).

Ahora se realiza la petición HTTP , el envio de los datos al archivo php.
Primero tenemos conexion.open('POST','ejemplo2.php')   aqui vamos a abrir la conexion y le estamos indicando que la conexion será de tipo POST y le vamos a pasar la ruta del archivo al que nos vamos a conectar (como siempre explico aqui es importante que le indiquen bien la ruta yo tengo el archivo php en la misma carpeta que el html pero de no ser así tiene que indicar la ruta completa).
Despues tenemos conexion.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); es muy importante que se ponga esta información si no todos los datos enviado  el servidor no les va a ser caso, por lo tanto no va a funcionar (generalmente envia error Undefined index:).

Por ultimo tenemos conexion.send("comentarios="+comentarios); Aqui es donde vamos a enviar los datos. La manera en que se envía los datos es  una cadena de texto que se vería algo así:
'localhost/ejemplo2.php?comentarios=comentario',    Y esa cadena que sigue del signo de interrogación es la que vamos a poner en este campo. Si fueran más datos lo que se enviarían se pone un & y luego el nombre del siguiente dato = y la varibale que va a enviar por ejemplo:
'localhost/ejemplo2.php?comentarios=comentario&otra=otravariable' y quedaría entonces así:
conexion.send("comentarios="+comentarios+"&otra="+otravariable);
 
respuesta();
La función respuesta es donde vamos a manejar la información que hayamos resivido del archivo php
pero para esto tenemos unas condiciones primero
if(conexion.readyState == 4) esto quiere decir que si el estado de conexión es completo (4) entonces pasamos a la siguiente condición
if(conexion.status == 200) esto quiere decir que si el estado devualto por el HTTP fue "OK" entonces vamos a insertar  la respuesta del servidor en forma de texto conexion.responseText dentro del objeto 'respuesta' (que es el div).
Despues le agregue un setTimeout para que despues de 5 segundos mande llamar a la función limpiar();

limpiar()
Y por ultimo lo que la función limpiar va a ser, es remover lo que haya dentro del div 'respuesta'
por lo que 5 segundos despues de que aparezca el mensaje de que el mensaje ha sido enviado correctamente va a desaparecer. 

Ahora vamos con el archivo PHP

Antes de todo les comento que hice una bd llamada test y una tabla cometarios (si, sin n, error de dedo jeje a todos nos pasa) en donde tengo dos campos id y mensaje el id es int y autoincremet y el campo mensaje es de tipo TEXT ok.

Ahora si ahí les va a el código:

<?php
$mysqli=new mysqli("localhost", "root", "","test");
if($mysqli->connect_errno){
    echo "Fallo al conectar a MySQL:(". $mysqli->connect_errno.")". $mysqli->connect_errno;
}
$mensaje=$_POST['comentarios'];

$insertar=$mysqli->query("INSERT INTO cometarios (mensaje) VALUES ('$mensaje')");
if($insertar){
     echo "<b>Su mensaje ha sido enviado con &eacute;xtito</b>";
}

mysqli_close($mysqli);

?> 

Esta super sencillito es una conexión a mi base de datos donde si no se conecta va a mandar un error. Luego tenemos la variable $mensaje que va a ser igual a 'comentarios' que es la variable que estamos mandando por medio de POST desde el archivo html.
despues hacemos el INSERT vamos a insertar en el campo mensaje el contenido de la variable $mensaje (que es el comentario)
ahora la condición si el insert es TRUE (no hubo error al insertar ) entonces va a imprimir el mensaje de éxito. "Su mensaje ha sido enviado con éxito" el &eacute; es para el acento en la e ok se puede poner el encode pero yo ya me acostumbre a hacerlo así jejeje. ok
Despues cerramos la conexión a la base de datos. y Listo



Es todo ahora yo no puse mensaje de error pero uds. si lo podrían poner en caso de que no se haya insertado correctamente mandar un error .  que se verá en el div 'respuesta' de su formulario.

Como pueden ver es muy sencillo, aquí no necesitamos conexión a jquery ni nada solo con la condición dependiendo del formulario la conexión a XMLHttpRequest y Listo.
Sigan practicando y ya saben cualquier duda, error en el código, o alguna idea o sugerencia de ejemplo para poner el blog no duden en dejarla en los comentario abajo   


"Programar no tiene que ser tan difícil como parece...."

9 comentarios:

  1. hola que tal te agradezco muchisimo por el ejemplo , lo he capturado y ejecutado utilizando el wampserver, pero tengo una duda la primera vez que lo ejecuta guardo exitosamente el comentario en la bd, pero cuando intente guardar de nuevo otro comentario este ya no lo guarda

    ResponderEliminar
    Respuestas
    1. Y te manda algun error?? o simplemente no lo carga...

      Eliminar
  2. buenos dias, yo tambien lo ejequete pero no me carga, es decir no me sale el mensaje diciendo que los datos han sido cargados con exito

    ResponderEliminar
    Respuestas
    1. Revisaste tu base de datos a ver si te esta insertando? corre primero el php con un dato especifico para ver si el error esta en la consulta de mysql o si el erro esta en el archivo html.

      Eliminar
  3. como envio un formulario completo de registro

    ResponderEliminar
    Respuestas
    1. Para mandarlo con Ajex necesitas leer el value de cada uno de los campos de tu formulario y mandar como parametro esas variables.
      var c1=encodeURIComponent(document.getElementById("campo1").value);
      var c2=encodeURIComponent(document.getElementById("campo2").value);

      y esos los pasas en el conexion.send("comentarios="+comentarios+"

      Eliminar
  4. Me funciono bien gracias!, tengo una duda si tengo 2 formularios distintos tendría que hacer esto 2 veces(distintos) o puedo reutilizar alguna porción del codigo y como lo tendría que hacer

    ResponderEliminar
    Respuestas
    1. Disculpa la demora de la respuesta. pero me da mucho gusto que te haya funcionado. Puedes reutilizar el código lo que podrías hacer es meter una variable. Y en el codigo tomar esa variable si es de form1 1 haga una casa y si es de form2 haga otra.

      Eliminar