El objetivo de este tutorial es empezar a desarrollar profesionalmente utilizando el Stack MEAN: MongoDB + Express + Angular + Node.
Vamos a crear una SPA (Single Page Aplication) con Angular, utilizaremos un API REST (Express + Node) con MongoDB como base de datos.
Estructura del proyecto
MeanApp
-- app // Backend
---- models
------ client.js
---- controllers
------ clients.js
---- routes.js
-- public // Frontend
---- index.html
---- main.js
-- server.js // Express Server
-- package.json
Empezaremos por package.json para indicar que dependencias vamos a necesitar:
{ "name": "nodejs-angular-apirest", "version": "1.0.0", "description": "MEAN stack", "main": "server.js", "dependencies": { "body-parser": "~1.13.2", "debug": "~2.2.0", "morgan": "~1.6.1", "express": "~4.13.1", "method-override": "^2.1.2", "mongoose": "~3.6.11" } }
Después de esto, en una terminal ejecutamos npm install
y se nos instalarán las dependencias para poder empezar a utilizarlas.
Implementando nuestro Express Server
Ahora pasaremos al archivo server.js que será el fichero donde esté la configuración del servidor, así como la conexión a la base de datos y las rutas de nuestro API.
Como todo fichero de servidor Express, primero añadimos las librerías que necesitamos, las configuraciones y rutas:
// Dependencies // ----------------------------------------------------- var express = require('express'); var path = require('path'); var logger = require('morgan'); var bodyParser = require('body-parser'); var mongoose = require('mongoose'); var morgan = require('morgan'); var methodOverride = require('method-override'); var app = express(); // Express Configuration // ----------------------------------------------------- // Sets the connection to MongoDB mongoose.connect('mongodb://localhost:27017/mean', function(err, res) { if(err) throw err; console.log('Connected to Database'); }); // Logging and Parsing app.use(express.static(path.join(__dirname, 'public'))); // sets the static files location to public app.use(morgan('dev')); // log with Morgan app.use(bodyParser.json()); // parse application/json app.use(bodyParser.urlencoded({extended: false})); // parse application/x-www-form-urlencoded app.use(methodOverride()); // Routes // ------------------------------------------------------ require('./app/routes.js')(express,app); // Catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // Listen // ------------------------------------------------------- app.listen(3000, function() { console.log('App listening on port 3000'); });
Creación del modelo
El siguiente paso es construir el modelo de la base de datos. Esto lo hacemos con Mongoose y nuestro modelo será muy sencillo ya que solo cuenta con un atributo “name”. Este código lo insertamos en client.js (dentro de la carpeta models de la carpeta app):
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var clientSchema = new Schema({ name: { type: String, required: true }, created_at: {type: Date, default: Date.now}, updated_at: {type: Date, default: Date.now} }); // Sets the created_at parameter equal to the current time clientSchema.pre('save', function(next){ now = new Date(); this.updated_at = now; if(!this.created_at) { this.created_at = now } next(); }); module.exports = mongoose.model('Client', clientSchema);
Rutas del API
Tras esto nos queda construir las rutas que llamarán a nuestro API y que utilizaremos desde el frontend. En esta tabla se muestran las 3 llamadas que vamos a implementar y que definirán nuestra API:
HTTP | URL | Descripción |
---|---|---|
GET | /api/v1/clients | Devuelve todos los clientes. |
POST | /api/v1/clients | Crea un cliente. |
DELETE | /api/v1/clients/:id | Borra un cliente. |
Veamos las rutas. Estas irán también en el archivo routes.js (dentro de la carpeta app):
// Dependencies var ClientCtrl = require('./controllers/clients.js'); // Opens App Routes module.exports = function(express,app) { // HOME app.get('/', function(req, res, next) { res.sendfile('./public/index.html'); }); //API var api = express.Router(); //Clients api.route('/clients') .get(ClientCtrl.findAll) .post(ClientCtrl.add); api.route('/clients/:id') .get(ClientCtrl.findById) .put(ClientCtrl.update) .delete(ClientCtrl.delete); app.use('/api/v1/', api); };
Creación del controlador
Para que nuestro proyecto sea más ordenado, recomiendo crear los controladores en la carpeta «controllers» dentro de la carpeta «app», en este caso sería clients.js:
// Dependencies var mongoose = require('mongoose'); var Client = require('../models/client.js'); //GET - Return all registers exports.findAll = function(req, res) { Client.find(function(err, clients) { if(err) return res.status(500).send(err.message); res.status(200).json(clients); }); }; //GET - Return a register with specified ID exports.findById = function(req, res) { Client.findById(req.params.id, function(err, client) { if(err) return res.status(500).send(err.message); res.status(200).json(client); }); }; //POST - Insert a new register exports.add = function(req, res) { var client = new Client({ name: req.body.name }); client.save(function(err, client) { if(err) return res.status(500).send(err.message); res.status(200).json(client); }); }; //PUT - Update a register already exists exports.update = function(req, res) { Client.findById(req.params.id, function(err, client) { var client = new Client({ name: req.body.name }); client.save(function(err) { if(err) return res.status(500).send(err.message); res.status(200).json(client); }); }); }; //DELETE - Delete a register with specified ID exports.delete = function(req, res) { Client.findById(req.params.id, function(err, client) { client.remove(function(err) { if(err) return res.status(500).send(err.message); res.status(200).send(); }); }); };
Desarrollo de la parte Frontend con AngularJS
Todo lo que hemos hecho hasta ahora corresponde al Backend de la aplicación. Ahora empezaremos con el desarrollo Frontend con Angular.
Tendremos toda la lógica en el fichero main.js (tiene que estar dentro de la carpeta public), primero crearemos un modulo que será el que defina toda nuestra aplicación:
angular.module('angularClient', []); function mainController($scope, $http) { $scope.formData = {}; getClients(); // Create Client $scope.createClient = function(){ $http.post('/api/v1/clients', $scope.formData) .success(function(data) { $scope.formData = {}; getClients(); }) .error(function(data) { console.log('Error:' + data); }); }; // Delete Client $scope.deleteClient = function(id) { $http.delete('/api/v1/clients/' + id) .success(function(data) { getClients(); }) .error(function(data) { console.log('Error:' + data); }); }; function getClients(){ $http.get('/api/v1/clients') .success(function(data) { $scope.clients = data; console.log(data) }) .error(function(data) { console.log('Error: ' + data); }); }; }
El código HTML completo del archivo index.html (tiene que estar dentro de la carpeta public) es:
<!doctype html> <html ng-app="angularClient"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Angular CLIENT app</title> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"> </head> <body ng-controller="mainController"> <div class="container"> <!--Cabecera--> <div class="jumbotron text-center"> <h1>Angular CLIENT List <span class="label label-info">{{ clients.length }}</span></h1> </div> <!--Lista de Todos--> <div id="client-list" class="row"> <div class="col-sm-4 col-sm-offset-4"> <div class="checkbox" ng-repeat="client in clients"> <label> <input type="checkbox" ng-click="deleteClient(client._id)"> {{ client.name }} </label> </div> </div> </div> <!--Formulario para insertar nuevos Todo--> <div id="client-form" class="row"> <div class="col-sm-8 col-sm-offset-2 text-center"> <form> <div class="form-group"> <input type="text" class="form-control input-lg text-center" placeholder="Inserta nuevo cliente" ng-model="formData.name"> </div> <button class="btn btn-primary btn-lg" ng-click="createClient()">Añadir</button> </form> </div> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script> <script src="main.js"></script> </body> </html>
Por más información acerca de Angular, ingresar a este link.
Y ya tenemos nuestra aplicación. Solo tenemos que correr el servidor en un terminal con node server.js e ir a un navegador a la URL http://localhost:3000 y tendremos algo como esto:
Descargar proyecto completo: