---
title: MEAN (Mongo-Express-Angular-Node) Ejemplo de Aplicación Web (Parte II)
url: https://jarroba.com/mean-mongo-express-angular-node-ejemplo-de-aplicacion-web-parte-ii/
author: Richard [Admin Jarroba]
date: 2014-07-24
modified: 2026-10-21
language: es
license: CC BY-NC-SA 3.0 (https://creativecommons.org/licenses/by-nc-sa/3.0/) — attribution: "MEAN (Mongo-Express-Angular-Node) Ejemplo de Aplicación Web (Parte II)", Richard [Admin Jarroba], jarroba.com
categories: Tecnologias Web
tags: angular, express, MEAN, MEANJS, mongo, mongodb, node, nodejs
series: MEAN: Mongo, Express, Angular y Node (part 2 of 2)
repository: https://github.com/jarroba/MEAN_ejemplo
---

# MEAN (Mongo-Express-Angular-Node) Ejemplo de Aplicación Web (Parte II)

> Construimos paso a paso una aplicación web con MEAN: una API REST con Node y Express sobre MongoDB y un frontend en AngularJS con un CRUD de personas.

El proyecto de este post lo puedes descargar pulsando [AQUI](https://github.com/jarroba/MEAN_ejemplo).

 

En esta entrada vamos a mostrar un ejemplo muy sencillo de como desarrollar una sencilla aplicación web utilizando MEAN (**M**ongo-**E**xpress-**A**ngular-**N**ode). Si no sabes lo que es MEAN y sus características te recomiendo que leas la entrada «[MEAN (Mongo-Express-Angular-Node) Desarrollo Full Stack JavaScript (Parte I)](https://jarroba.com/mean-mongo-express-angular-node-desarrollo-full-stack-javascript-parte-i/)". Para poder entender más o menos bien este tutorial, es recomendable que tengas conocimientos básicos de MongoDB (por lo menos que sepas lo que es un CRUD o saber hacerlo) y saber por lo menos (aunque no sepas hacerlo) que es un API REST y los 4 tipos de llamadas que hay (Get, Post, Put y Delete).

 

Por hacer un pequeño resumen MEAN utiliza las tecnologías de MongoDB, Express, AngulaJS y NodeJS para hacer aplicaciones web y lo bueno de todas ellas es que utiliza el mismo lenguaje de programación, ***Javascript***. En resumen este tipo de aplicaciones consiste en desarrollar una ***API REST con NodeJS y Express*** y esta API puede hacer un CRUD (**C**reate-**R**ead-**U**pload-**D**elete) a la***base de datos de MongoDB***. Con este API REST se comunicará ***AngularJS (que es el Frontend)***haciendo peticiones (Get, Post, Put y Delete) cuyos datos se tendrán actualizados en la web (Single-Page-Application):

 

[![MEAN_arquitectura_jarroba](https://jarroba.com/wp-content/uploads/2014/07/MEAN_arquitectura_jarroba.png)](https://jarroba.com/wp-content/uploads/2014/07/MEAN_arquitectura_jarroba.png)

 

En esta entrada vamos a hacer una aplicación web muy sencilla que consistirá en hacer un CRUD de objetos «Persona» a través de un formulario y una tabla para visualizarlos. De esta forma mostraremos como hacer las 4 peticiones al API REST (Get, Post, Put y Delete) y el CRUD en la base de datos (Los que no sepáis qué es MongoDB y vengais del mundo SQL, un CRUD es lo mismo que «*Altas, Bajas, Modificaciones y Consultas*"). En la siguiente imagen vemos lo que hará la aplicación; y será hacer un "Read" de todos los objetos "Persona" que hay en la base de datos para mostrarlos en la tabla; podrá "Registrar" ("Create") un objeto "Persona" a través del formulario de la derecha y una vez que seleccionemos una fila de la tabla, lo rellenará en el formulario y lo podremos "Modificar" ("Update") o "Borrar" ("Delete"). Por otro lado desde el fichero HTML validaremos el formulario con las directivas que nos proporciona AngularJS.

 

[![Ejm_MEAN_jarroba](https://jarroba.com/wp-content/uploads/2014/07/Ejm_MEAN_jarroba.png)](https://jarroba.com/wp-content/uploads/2014/07/Ejm_MEAN_jarroba.png)

 

Bueno ahora vamos al lio. Lo primero que tienes que hacer es instalarte NodeJS, Express y MongoDB en tu máquina o entorno de desarrollo. En este tutorial no vamos a explicar como hacerlo ya que según el sistema operativo que utilices se hará de una forma o de otra. De todas formas existen muchos tutoriales por internet de como hacerlo para los diferentes sistemas operativos. Aviso que Instalar NodeJS y Express en Windows es bastante tedioso, así que intenta hacerlo en un Linux o Unix.

 

[![MEAN_ejemplo_jarroba](https://jarroba.com/wp-content/uploads/2014/07/MEAN_ejemplo_jarroba.png)](https://jarroba.com/wp-content/uploads/2014/07/MEAN_ejemplo_jarroba.png)En esta imagen vemos cual va a ser la estructura del proyecto que vamos a desarrollar. En ella hay una carpeta "angular" que tiene los ficheros del frontend ("index.html") con una Single-Page-Application y el fichero que hará las llamadas al API REST ("core.js") y que mantendrá el modelo actualizado para que se muestre en la web.

 

En la carpeta «app» vamos a tener el API REST que lo hemos hecho con NodeJS y Express. En ella tendremos el fichero «persona.js» en la que tenemos definido el modelo del objeto «Persona» y las rutas (o endpoints) de nuestra API REST. Dentro del «controller.js» están las funciones que se ejecutan al llamar a cada ruta.

 

Por último tenemos los ficheros "package.json" para ver las dependencias que se necesitaran y luego el fichero "server.js" en el que estará la configuración del servidor. Ahora vamos a mostrar el código fuente de estos ficheros:

 

En primer lugar mostramos el fichero "Package.json" que a parte de la información relacionada con el proyecto nos indicará las dependencias que vamos a necesitar para el proyecto (este Package.json es algo parecido a Composer en Symphony o a Maven en Java para que os hagáis una idea). En este caso vamos a necesitar las librerías de "mongose" y "express". Express ya explicamos lo que es y "mongose" nos permitirá definir el modelo de datos que se guardará en MongoDB. Otra cosa muy importante (y de esto depende que funcione o no el proyecto) es que se ponga la versión correcta tanto de express como de mongose que se vaya a utilizar y no se os ocurra poner como versión la "latest" porque no funcionará cuando cambien de versión. El código de este fichero es el siguiente:

 

```json

{
  "name"         : "ejemploMEAN",
  "version"      : "0.0.1",
  "description"  : "Sencilla app con MEAN",
  "main"         : "server.js",
  "author"       : "Ricardo Moya",
  "dependencies" : {
    "express"    : "~3.4.4",
    "mongoose"   : "~3.6.2"
  }
}
```

 

El siguiente fichero que vamos a ver es el «server.js» en el cual configuraremos el servidor. En el vamos a definir qué librerías utilizaremos (express y mongose) y el puerto por el que «escuchara» la aplicación. Hemos definido el puerto 8080 pero definid el puerto que queráis y que este libre. También haremos la conexión a la base de datos Mongo («mongodb://localhost:27017/MeanExample») y cargaremos las rutas o endpoints de nuestra aplicación («routes.js»).

 

```javascript

// Inicialización
var express  = require('express');
var app      = express(); 					// Utilizamos express
var mongoose = require('mongoose'); 				// mongoose para mongodb
var port  	 = process.env.PORT || 8080; 			// Cogemos el puerto 8080

// Configuracion
mongoose.connect('mongodb://localhost:27017/MeanExample'); 	// Hacemos la conexión a la base de datos de Mongo con nombre "MeanExample"

app.configure(function() {
	app.use(express.static(__dirname + '/angular')); 		
	app.use(express.logger('dev')); 			// activamos el log en modo 'dev'
	app.use(express.bodyParser());
	app.use(express.methodOverride());
});

// Cargamos los endpoints
require('./app/routes.js')(app);

// Cogemos el puerto para escuchar
app.listen(port);
console.log("APP por el puerto " + port);
```

 

Ahora vamos a pasar a explicar como hemos hecho el API REST con NodeJS. En primer lugar vamos a mostrar el modelo de datos que utilizaremos. Eso esta en el fichero "persona.js" y simplemente hemos definido un modelo con nombre, apellido y edad que son todos un String para hacer más simple la app. Su contenido es el siguiente:

 

```javascript

var mongoose = require('mongoose');

module.exports = mongoose.model('Persona', {
	nombre: String,
	apellido: String,
	edad: String
});
```

 

En el fichero "routes.js" definiremos los endpoints de la API REST y sus acciones. Para hacer un ejemplo lo más completo posible, hemos hecho las 4 tipos de llamadas (Get, Post, Put y Delete):

 

```javascript

var Persona = require('./modelo/persona');
var Controller = require ('./controller');

module.exports = function(app) {

	// devolver todos los Personas
	app.get('/api/persona', Controller.getPersona);
	// Crear una nueva Persona
	app.post('/api/persona', Controller.setPersona);
	// Modificar los datos de una Persona
	app.put('/api/persona/:persona_id', Controller.updatePersona);
	// Borrar una Persona
	app.delete('/api/persona/:persona_id', Controller.removePersona);
	// application 
	app.get('*', function(req, res) {
		res.sendfile('./angular/index.html'); // Carga única de la vista
	});
};
```

 

En el fichero "controller.js" escribimos las funciones de cada llamada de la API REST:

 

```javascript

var Persona = require('./modelo/persona');

// Obtiene todos los objetos Persona de la base de datos
exports.getPersona = function (req, res){
	Persona.find(
		function(err, persona) {
			if (err)
				res.send(err)
					res.json(persona); // devuelve todas las Personas en JSON		
				}
			);
}

// Guarda un objeto Persona en base de datos
exports.setPersona = function(req, res) {

		// Creo el objeto Persona
		Persona.create(
			{nombre : req.body.nombre,apellido: req.body.apellido, edad: req.body.edad}, 
			function(err, persona) {
				if (err)
					res.send(err);
				// Obtine y devuelve todas las personas tras crear una de ellas
				Persona.find(function(err, persona) {
				 	if (err)
				 		res.send(err)
				 	res.json(persona);
				});
			});

	}

// Modificamos un objeto Persona de la base de datos
exports.updatePersona = function(req, res){
	Persona.update( {_id : req.params.persona_id},
					{$set:{nombre : req.body.nombre,apellido: req.body.apellido, edad: req.body.edad}}, 
					function(err, persona) {
						if (err)
							res.send(err);
				// Obtine y devuelve todas las personas tras crear una de ellas
				Persona.find(function(err, persona) {
				 	if (err)
				 		res.send(err)
				 	res.json(persona);
				});
			});
	}

// Elimino un objeto Persona de la base de Datos
exports.removePersona = function(req, res) {
	Persona.remove({_id : req.params.persona_id}, function(err, persona) {
		if (err)
			res.send(err);
			// Obtine y devuelve todas las personas tras borrar una de ellas
			Persona.find(function(err, persona) {
				if (err)
					res.send(err)
				res.json(persona);
			});
		});
}
```

 

Llegados a este punto ya tenemos el API REST con NodeJS desarrollado y tendremos ahora que "unirlo" con AngularJS; es decir el frontend.

 

Dentro de Angular tenemos los ficheros "core.js" e "index.html". El fichero "core.js" será el encargado de hacer la peticiones al API REST y de tener actualizados los modelos de datos para que los muestre la web; es decir, que AngularJS tiene el "AJAX" por defecto aunque no sea 100% correcto lo que estoy diciendo. El contenido del fichero "core.js" es el siguiente:

 

```javascript

angular.module('MainApp', [])

function mainController($scope, $http) {
	$scope.newPersona = {};
	$scope.personas = {};
	$scope.selected = false;

	// Obtenemos todos los datos de la base de datos
	$http.get('/api/persona').success(function(data) {
		$scope.personas = data;
	})
	.error(function(data) {
		console.log('Error: ' + data);
	});

	// Función para registrar a una persona
	$scope.registrarPersona = function() {
		$http.post('/api/persona', $scope.newPersona)
		.success(function(data) {
				$scope.newPersona = {}; // Borramos los datos del formulario
				$scope.personas = data;
			})
		.error(function(data) {
			console.log('Error: ' + data);
		});
	};

	// Función para editar los datos de una persona
	$scope.modificarPersona = function(newPersona) {
		$http.put('/api/persona/' + $scope.newPersona._id, $scope.newPersona)
		.success(function(data) {
				$scope.newPersona = {}; // Borramos los datos del formulario
				$scope.personas = data;
				$scope.selected = false;
			})
		.error(function(data) {
			console.log('Error: ' + data);
		});
	};

	// Función que borra un objeto persona conocido su id
	$scope.borrarPersona = function(newPersona) {
		$http.delete('/api/persona/' + $scope.newPersona._id)
		.success(function(data) {
			$scope.newPersona = {};
			$scope.personas = data;
			$scope.selected = false;
		})
		.error(function(data) {
			console.log('Error: ' + data);
		});
	};

	// Función para coger el objeto seleccionado en la tabla
	$scope.selectPerson = function(persona) {
		$scope.newPersona = persona;
		$scope.selected = true;
		console.log($scope.newPersona, $scope.selected);
	};
}
```

 

Visto este fichero habréis visto un par de cosas un poco extrañas como son la variable que se pasa como parámetro "*$scope*" y la primera linea que pone: "*angular.module('MainApp', [])*". Esto es un poco complicado de entender sino tenéis experiencia en el desarrollo de aplicaciones web. Si habéis trabajado con el framework de Spring en Java os sonará esa etiqueta y es algo similar. Dado que este es un tutorial para tener una primera toma de contacto con MEAN no vamos a explicar esto en detalle, pero dejamos un enlace de la documentación de Angular ([AngularJS — Superheroic JavaScript MVW Framework](https://angularjs.org/)) para que lo veáis más adelante si queréis profundizar más en AngularJS.

 

Por último vamos a mostrar el "index.html" que es donde esta lo curioso de AngularJS (Para esta página hemos utilizado los estilos CSS de [bootstrap](http://getbootstrap.com/). Para saber más sobre bootstrap mirar la entrada "Bootstrap o cómo facilitar el desarrollo Frontend"). Lo primero que hacemos es cargar las librerías de AngularJS de su página web:

 

```xml

<!-- Cargamos angular -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
```

 

Luego cargamos el fichero "core.js" donde tendremos las funciones que harán las llamadas el API REST y nos mantendrán el modelo actualizado:

 

```xml

<!-- Cargamos el javascript de angular -->
<script src="core.js"></script>
```

 

Otra cosa que vais a ver en el "index.html" son una serie de anotaciones que empiezan por "**ng-xxx**«. Estas son etiquetas propias de AngularJS y que tenéis que mirar en la documentación para saber que hacen o lo que queréis que hagan. Si veis al principio tenemos la etiqueta *ng-app="MainApp"* que es el contexto en el se encuadra esta vista. Vemos también otras etiquetas como *ng-model, ng-repeat, ng-click, ng-disabled* y demás que son bastante intuitivas, pero en función de vuestras necesidades tendréis que utilizar unas etiquetas u otras.

 

Lo siguiente que vamos a ver es lo sencillo que es mostrar todos los datos de la base de datos en una tabla. Como vemos en el siguiente fragmento de código referente a la tabla, vemos que tenemos la etiqueta "*ng-repeat*" y le indicamos que nos vaya cogiendo un objeto "*persona*" del array "*personas*" que tenemos definido en el "core.js". Una vez que tenemos el objeto "persona" lo pintamos en la tabla accediendo a sus atributos ({{ persona.nombre }}, {{ persona.apellido }},…). En definitiva este "*ng-repeat*" funciona igual que un bucle "foreach". Con la etiqueta "*ng-click*" ejecutaremos la función "*selectPerson(persona)*» que esta definida en el «core.js» y que cogerá el objeto persona que seleccionemos al pulsar una fila de la tabla para mostrarla en el formulario.

 

```xml

<table class="table table-striped">
    <tr class="info">
        <td>Nombre</td>
        <td>Apellidos</td>
        <td>Edad</td>
    </tr>
    <tr ng-repeat="persona in personas" ng-click="selectPerson(persona)">
        <td>{{ persona.nombre }}</td>
        <td>{{ persona.apellido }}</td>
        <td>{{ persona.edad }}</td> 
    </tr>
</table>
```

 

Ahora vamos a ver como hemos hecho el formulario y como hemos hecho una sencilla validación del mismo, impidiendo registrar una persona sino tiene sus campos rellenos o modificarlo y borrarlo sino ha sido seleccionado. En este formulario definimos los "*input*" y al final de cada input ponemos a que atributo del objeto persona corresponde y al poner "*required*" indicamos que es un campo obligatorio.

 

```xml

<div class="form-group">
    <input type="text" class="form-control input-lg text-center" placeholder="Nombre" ng-model="newPersona.nombre" required>
    <input type="text" class="form-control input-lg text-center" placeholder="Apellido" ng-model="newPersona.apellido" required>
    <input type="text" class="form-control input-lg text-center" placeholder="Edad" ng-model="newPersona.edad" required>
</div>
```

 

Después tenemos que definir las diferentes acciones del formulario. Dentro de todos los botones definimos las funciones que se tienen que ejecutar tras pulsar el botón con la etiqueta "*ng-click*". Por otro lado inhabilitaremos (poniendo "*ng-disabled*") los botones sino cumplen los requisitos para hacer cada una de las acciones, como que los atributos no sean nulos, etc.

 

```xml

<!-- Acciones que podemos realizar en el formulario -->
<button type="submit" class="btn btn-success btn-lg" ng-click="registrarPersona()" ng-disabled="myForm.$invalid || selected">Registrar</button>
<button type="submit" class="btn btn-warning btn-lg" ng-click="modificarPersona(newPersona)" ng-disabled="!newPersona.nombre || !newPersona.apellido || !newPersona.edad || !selected">Modificar</button>
<button type="submit" class="btn btn-danger btn-lg" ng-click="borrarPersona(newPersona)" ng-disabled="!newPersona.nombre || !newPersona.apellido || !newPersona.edad || !selected">Borrar</button>
```

 

Respecto al formulario no hemos hecho una validación muy exhaustiva pero AngularJS nos permitirá validar muchas cosas como que el campo deba ser un email, que cumpla cierta expresión regular, etc. A continuación mostramos todo el código del «index.html» para que lo veáis entero en su contexto.

 

```xml

<!doctype html>

<html ng-app="MainApp">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Ejemplo MEAN</title>
	<!-- Cargamos bootstrap -->
	<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
	<!-- Cargamos angular -->
	<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
	<!-- Cargamos el javascript de angular -->
	<script src="core.js"></script>

</head>
<body ng-controller="mainController">
	<div class="container">

		<div class="jumbotron text-center" ng-prueba>
			<h1>Nº de Registros: <span class="label label-success">{{ personas.length }}</span></h1>
		</div>

		<div class="row">
			<div class="col-sm-6 col-sm-offset-1">
				<table class="table table-striped">
					<tr class="info">
						<td>Nombre</td>
						<td>Apellidos</td>
						<td>Edad</td>
					</tr>
					<tr ng-repeat="persona in personas" ng-click="selectPerson(persona)">
						<td>{{ persona.nombre }}</td>
						<td>{{ persona.apellido }}</td>
						<td>{{ persona.edad }}</td>						
					</tr>
				</table>					
			</div>
			<div class="col-sm-4 col-sm-offset-1 text-center">
				<form name="myForm">
					<div class="form-group">
						<input type="text" class="form-control input-lg text-center" placeholder="Nombre" ng-model="newPersona.nombre" required>
						<br>
						<input type="text" class="form-control input-lg text-center" placeholder="Apellido" ng-model="newPersona.apellido" required>
						<br>
						<input type="text" class="form-control input-lg text-center" placeholder="Edad" ng-model="newPersona.edad" required>
					</div>

					<!-- Acciones que podemos realizar en el formulario -->
					<button type="submit" class="btn btn-success btn-lg" ng-click="registrarPersona()" ng-disabled="myForm.$invalid || selected">Registrar</button>
					<button type="submit" class="btn btn-warning btn-lg" ng-click="modificarPersona(newPersona)" ng-disabled="!newPersona.nombre || !newPersona.apellido || !newPersona.edad || !selected">Modificar</button>
					<button type="submit" class="btn btn-danger btn-lg" ng-click="borrarPersona(newPersona)" ng-disabled="!newPersona.nombre || !newPersona.apellido || !newPersona.edad || !selected">Borrar</button>
				</form>
			</div>
		</div>
	</div>
</body>
</html>
```

 

### ¿Poner en funcionamiento el proyecto?

 

Como ya hemos dicho no vamos a explicar como instalar NodeJS, Express y MongoDB ya que dependiendo del sistema operativo que utilicéis se hará de una forma o de otra y en Windows por ejemplo es bastante tedioso instalar esta herramientas, así que una vez que lo tengáis instalado todo debéis seguir los siguientes pasos:

 
1. **npm install** : teneis que ejecutar este comando en la carpeta del proyecto para que se descargue las librerías de express y mongose, es decir las dependencias del proyecto (si tenéis problemas hacerlo como «sudo» o superusuario). Salvando las distancias, esta acción es similar a hacer un «composer install» en symphony o descargarte los «.jar» definidos en el fichero «pom.xml» de Maven en Java. 

 

```bash

npm install
```
2. **node server.js**: En la carpeta del proyecto tenéis que lanzar este comando. Sino os funciona este poner «nodejs server.js». Este comando es para poner a correr el servidor y que el proyecto funcione. 

 

```bash

node server.js
```
3. **http://localhost:8080**: Ya podemos ver nuestra aplicación web yendo al navegador y poniendo la URL de vuestra máquina local donde tengáis el proyecto. Como ya he dicho podéis poner el puerto que queráis siempre que esté libre, pero lo tenéis que definir en el fichero «server.js». 

 

```text

http://localhost:8080
```

 

## CONCLUSIONES Y ACLARACIONES:

 

En esta entrada hemos visto como hacer un "sencillo" proyecto en MEAN. Quiero dejar muy claro que hacer un proyecto en MEAN es relativamente complejo y que en esta entrada nos hemos dejado muchas cosas sin explicar. Aun así es un buen punto de partida para empezar con MEAN, ver la arquitectura, el flujo de datos y una aplicación web en funcionamiento. Espero que os sirva esta entrada como punto de partida para empezar con MEAN.

## Serie: MEAN: Mongo, Express, Angular y Node

1. [MEAN (Mongo-Express-Angular-Node) Desarrollo Full Stack JavaScript (Parte I)](https://jarroba.com/mean-mongo-express-angular-node-desarrollo-full-stack-javascript-parte-i.md)
2. [MEAN (Mongo-Express-Angular-Node) Ejemplo de Aplicación Web (Parte II)](https://jarroba.com/mean-mongo-express-angular-node-ejemplo-de-aplicacion-web-parte-ii.md)

