En este post mostraré cómo conectarnos a nuestra base de datos con Angular. Para poder realizarlo, Angular dispone del servicio $http. Si el tema de los servicios te resulta nuevo puedes ver en qué consisten y cómo crear el tuyo propio.
El servicio $http nos permite comunicarnos con nuestro servidor vía objeto XMLHttpRequest. Si has programado alguna vez en jQuery, el método Ajax es muy parecido a lo que vamos a realizar.
Este sería un pequeño ejemplo de de $http
1 2 3 4 5 6 7 8 9 |
var promise = $http({method: 'POST', url: 'ruta/al/script/bd.php', data: losDatos}); promise.success(function (data, status, headers, config, statusText) { //Este callback se realiza cuando la llamada ha sido un éxito }); promise.error(function (data, status, headers, config, statusText) { //Este callback se realiza cuando la llamada ha tenido un error }); |
Aviso: Este sería un ejemplo con Angular 1.2. De esta versión en adelante hay algunas variaciones, pero el procedimiento es el mismo.
El servicio $http
El servicio $http tiene como argumento un objeto (literal) de configuración. El objeto de configuración puede aceptar más atributos pero para lo que vamos a necesitar esto nos llega. En el indicamos mediante la propiedad url el endpoint o destino de la llamada y qué método emplearemos, en este caso POST. Además, usamos la propiedad data para pasar los datos que queremos enviar al servidor.
El servicio $http devuelve un objeto promise. Promise es un estándar de JavaScript que presenta un valor que no está disponible aun, pero lo estará en un momento del futuro. Este valor indica el estado de la tarea de la llamada Ajax al servidor. Este objeto puede tener diferentes estados en este caso vemos si es un éxito o un error. Esto es muy similar al método de Ajax de jQuery, donde podíamos indicar que hacer en caso de que la petición fuese hecha, haya fallado o haya sido un éxito. Ambos promises aceptan funciones callback y argumentos como vemos en el ejemplo anterior:
1 |
function(data, status, headers, config, statusText) { } |
Estos argumentos de la funciones callback tienen los siguientes funciones:
Nombre | Tipo | Descripción |
---|---|---|
data | string u objeto | Contiene los datos de la respuesta. |
status | número | Código de estado HTTP (400,404,500…) |
header | function([nombreHeader] | La función getter del Header de la respuesta HTTP |
config | objeto | El objeto de configuración que fue usado para generar la petición |
statusText | string | Texto de la respuesta del estado HTTP |
Caso práctico
Creación del servicio
Para acceder a nuestra base de datos con Angular, vamos a emplear el servicio $http para nuestro propio servicio que llamaremos usuarioDataService. En principio, la finalidad de este servicio es de registrar a los usuarios pero se podría implementar otras funciones para loguear, cambiar contraseñas, modificar datos etc.. Si no tienes claro los conceptos de creación de un servicio, te recomiendo este post.
1 2 3 4 5 6 7 8 9 10 11 12 |
var module = angular.module('myapp', []); module.factory('usuarioDataService', function ($http) { var usuarioData = {}; usuarioData.registrar = function (datosUsuario) { var promise = $http({method: 'POST', url: 'registro.php', data: datosUsuario}); return promise; } return usuarioData; }); |
En este código registramos el servicio usuarioDataService que implementa el $http. Dentro del servicio creamos un objeto llamado usuarioData. Este objeto es el que devolvemos en nuestra factory function y que tendrá todos los métodos de nuestro servicio. En este caso, le incorporamos el método registrar().
El método «registrar» tiene un argumento: los datos pedidos en el formulario de registro, que haremos más adelante. Vemos que devuelve un objeto promise donde se llama al servicio $http. Dicho servicio se conectará vía POST a un script php que se encarga de guardar los datos del usuario (datosUsuario).
Usando el servicio
En este apartado vamos a crear el controlador que llamará al servicio para conectarnos a nuestra base de datos con Angular y además recogerá y validará los datos del formulario. Te recomiendo que mires este post que escribí hace un tiempo donde podíamos crear un formulario validado por Angular.
Comenzamos creando el controlador que tendrá como argumentos el $scope y el servicio usuarioDataService. En él estará el objeto «persona» que será el que guarde los datos (modelo) y será enviado posteriormente a la base de datos.
1 2 3 4 5 6 7 8 9 10 11 12 |
module.controller("miControlador", function ($scope, usuarioDataService) { $scope.persona = {}; $scope.persona.newsletter = true; /*Este atributo nos servirá para rellenar el select más adelante*/ $scope.persona.canales = [ { value: "television", label: "Television" }, { value: "radio", label: "Radio" }, { value: "redes-sociales", label: "Redes Sociales"}, { value: "otro", label: "Otros"} ]; |
A continuación, agregamos una función de validación. Esta función revisará que los campos del formulario «formularioRegistro» cumplen con los requisitos de la validación HTML5( que esté completo o que sea un valor válido…)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$scope.validar = function () { $scope.nombreInvalid = false; $scope.apellidoInvalid = false; $scope.emailInvalid = false; $scope.medioInvalid = false; $scope.mostrarMensajeExito = false; $scope.mostrarMensajeError = false; if (!$scope.formularioRegistro.nombre.$valid) { $scope.nombreInvalid = true; } if (!$scope.formularioRegistro.apellido.$valid) { $scope.apellidoInvalid = true; } if (!$scope.formularioRegistro.email.$valid) { $scope.emailInvalid = true; } if (!$scope.formularioRegistro.medio.$valid) { $scope.medioInvalid = true; } |
Dentro de esta misma función, vamos a compromar que el formulario es válido. De ser así, llamaremos al método registrar de nuestro servicio, donde pasaremos el objeto persona que contiene todos los datos que el usuario ha introducido en el formulario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
if ($scope.formularioRegistro.$valid) { $scope.enProceso = true; var promise = usuarioDataService.registrar($scope.persona); promise.then(function (reponse, status) { $scope.mostrarMensajeExito = true; },function(data) { $scope.errorPromise = "Parece que ha habido un problema con tu petición"; if(data.status == 404) $scope.errorPromise = "Parece que no se ha encontrado el recurso solicitado"; $scope.mostrarMensajeError = true; }); promise.finally(function () { $scope.enProceso = false; }); $scope.doShow = true; } } |
Como el método de nuestro servicio nos devuelve un Promise, establecemos una serie de puntos. El primero con un then (equivalente al success) que pondrá a true la varable que permitirá mostrar el mensaje de éxito. Luego hay otra función separado con un coma que sería equivalente al error. En el establecemos un mensaje de error por defecto: «Parece que ha habido un problema con tu petición». Para probar un poco las variables que nos devuelve el callback, si la respuesta devuelve un error 404, cambiamos el mensaje.
Y para terminar un finally, que siempre se ejecutará y lo que hará será ocultar el mensaje de cargando y deshabilitar el botón submit cambiando de valor la variable «enProceso».
Crear el formulario de registro
En el formulario irán todos los campos con sus respectivas directivas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<body ng-app="myapp"> <div> <div ng-controller="miControlador"> <form name="formularioRegistro" ng-submit="validar()" novalidate> <div ng-show="mostrarMensajeExito"> Gracias por registrarte! </div> <div class="error" ng-show="mostrarMensajeError"> {{errorPromise}} </div> <input type="text" placeholder="Nombre" name="nombre" ng-model="persona.nombre" required/> <span ng-show="nombreInvalid"><br/>Introduzca un nombre</span> <br/> <input type="text" placeholder="Apellido" name="apellido" ng-model="persona.apellido" required/> <span ng-show="apellidoInvalid"><br/>Introduzca un apellido</span> <br/> <input type="email" placeholder="Email" name="email" ng-model="persona.email" required/> <span ng-show="emailInvalid"><br/>Introduzca un email válido</span> <br/> <select name="medio" ng-model="persona.medio" ng-options="obj.value as obj.label for obj in persona.canales" required> <option value="">Donde has oído hablar de nosotros?</option> </select> <span ng-show="medioInvalid"><br/>Indica donde has oído hablar de nosostros</span> <br/> <input ng-model="persona.newsletter" type="checkbox" name="newsletter" id="newsletter" value="newsletter"/> <label for="newsletter">Recibir newsletter</label> <br/> <input type="submit" value="Registro"/> <span ng-show="enProceso" style="padding-left:10px;"> <p>Cargando...</p> </span> </form> </div> </div> </body> |
Y si quieres darle un poco de diseño
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<style> body, input, select { font: normal 1em Helvetica; } input:not([type='checkbox']), select { width: 350px; } input, select { padding: 5px; margin-top: 12px; } input[name='email'].ng-dirty.ng-invalid-email { color: red; } input[name='email'].ng-dirty.ng-valid-email { color: green; } form span, .error { color: red; } </style> |
Generar la respuesta en el lado del servidor
Hasta aquí tenemos lo necesario para comunicarnos con el servidor. Ahora lo que nos hace falta es como reaccionará el servidor para que la conexión con la base de datos con Angular sea un éxtio. Lo primero es tener en cuenta es que recibiremos los datos en formato json, por tanto, ademas de recibirlo habrá que decodificarlo
1 2 |
$json = file_get_contents('php://input'); $obj = json_decode($json); |
Una vez tenemos los datos del formulario, realizamos la conexión a la base de datos y generamos su correspondiente consulta. Si te fijas, los valores de la tabla son los atributos del objeto «persona» recibido de Angular.
1 2 3 4 5 6 7 8 9 |
// Conectando, seleccionando la base de datos $link = mysqli_connect('localhost', 'root', '', 'test') or die('No se pudo conectar: ' . mysql_error()); // Realizar una consulta MySQL $query = "insert into usuario(nombre, apellido, email, medio, newsletter) values ('$obj->nombre', '$obj->apellido', '$obj->email','$obj->medio', '$obj->newsletter')"; $result = mysqli_query($link, $query) or die('Consulta fallida: ' . mysql_error()); |
Y si quisieras devolver una respuesta recuerda hacerlo en formato json. Para ello bastaría un simple array y la funcion json_encode. Por ejemplo, voy a devolver el ID del usuario introducido
1 2 |
$resultData = array("id"=>mysqli_insert_id($link)); echo json_encode($resultData); |
Y para recibirlo en Angular debería ir así
1 2 3 |
promise.then(function (reponse, status) { console.log(reponse.data.id); } |
La variable response contiene un objeto data que a su vez tiene el atributo id, que es el que hemos declarado en el array de PHP.
Resultado final
Una vez llegados aquí, podremos enviar los datos del formulario a la base de datos con Angular.
Como este post ha sido un poco extenso, dejo en mi GitHub todos los scripts, incluido el SQL de la creación de la tabla que he empleado en este tutorial.
Y hasta aquí cómo realizar una conexión a la base de datos con Angular, espero que os haya gustado. A seguir picando 🙂