Tutorial: Crear una aplicación web utilizando MEAN

| 2016-06-30 | No hay comentarios »

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 

mean-stack-tutorial

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:

clientmean

Descargar proyecto completo:

github-logo

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • Tutorial: Autenticación de usuarios en Node.js con Facebook utilizando Passport
  • Tutorial: Autenticación basada en Token utilizando Node.js + Express.js + MongoDB
  • Tutorial: Crear API RESTful utilizando Node.js + Express.js + MongoDB
  • Archivos estáticos en Express.js