and the rise of the machines
<form.io> provides developers an easy drag & drop interface that creates both forms and the REST API's in one easy step!
what makes it so darn special?
Let's look at how the web has evolved.
Applications must be made differently.
Forces us to develop our websites like a web application.
Angular.js enables
Multi-Service Applications
Helping us go from this...
To this...
Micro-service architecture
To adapt, we should get M.E.A.N
Why M.E.A.N?
An entire ecosystem of JavaScript
How we will defeat the "rise of the machines".
"API first"
mkdir server
cd server
npm init
npm install --save express
npm install --save mongoose
npm install --save resourcejs
npm install --save method-override
npm install --save body-parser
npm install --save lodash
server/index.jsvar express = require('express'); var mongoose = require('mongoose'); var bodyParser = require('body-parser'); var methodOverride = require('method-override'); var _ = require('lodash');
// Create the application. var app = express();
// Add Middleware necessary for REST API's app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json()); app.use(methodOverride('X-HTTP-Method-Override'));
// Connect to MongoDB mongoose.connect('mongodb://localhost/meanapp'); mongoose.connection.once('open', function() {
console.log('Listening on port 3000...'); app.listen(3000); });
Shell
node index.js
Output
Listening on port 3000...
If you to to http://localhost:3000 you will see the server is running, but nothing shows up. This is expected.
Let's add CORS support for RESTful interfaces.
server/index.js
...
...
app.use(methodOverride('X-HTTP-Method-Override'));
// CORS Support
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
mongoose.connect('mongodb://localhost/meanapp');
...
...
server/index.js
...
...
app.use('/hello', function(req, res, next) {
res.send('Hello World!');
next();
});
...
...
Now go to http://localhost:3000/hello in your browser.
This is the fundamental idea at registering REST endpoints at certain paths.
New file @ server/models/Movie.jsvar mongoose = require('mongoose');
// Create the MovieSchema. var MovieSchema = new mongoose.Schema({
title: { type: String, required: true }, url: { type: String, required: true } });
// Export the model. module.exports = mongoose.model('movie', MovieSchema);
New file @ server/models/index.js
module.exports = {
movie: require('./Movie')
};
server/index.js
...
...
mongoose.connection.once('open', function() {
// Load the models.
app.models = require('./models/index');
...
...
New file @ server/controllers/MovieController.jsvar Resource = require('resourcejs');
module.exports = function(app, route) {
// Setup the controller for REST Resource(app, '', route, app.models.movie).rest();
// Return middleware. return function(req, res, next) { next(); }; };
New file @ server/routes.js
module.exports = {
'movie': require('./controllers/MovieController')
};
server/index.js... ... app.models = require('./models/index'); // Load the routes. var routes = require('./routes');
_.each(routes, function(controller, route) {
app.use(route, controller(app, route)); }); ... ...
https://github.com/travist/meanapp/tree/resourcejs/server
cd server
node index.js
in AngularJS
http://yeoman.io/
mkdir client
cd client
npm install -g yo
npm install -g generator-angular
yo angular
yo angular:route movies
app/views/movies.html<table class="table table-striped"> <thead> <th>Title</th> <th>URL</th> </thead> <tbody>
<tr ng-repeat="movie in movies">
<td>{{ movie.title }}</td> <td>{{ movie.url }}</td>
</tr> </tbody> </table>
app/scripts/controllers/movies.js
angular.module('clientApp')
.controller('MoviesCtrl', function ($scope) {
$scope.movies = [
{
title: 'A New Hope',
url: 'http://youtube.com/embed/1g3_CFmnU7k'
},
{
title: 'The Empire Strikes Back',
url: 'http://youtube.com/embed/96v4XraJEPI'
},
{
title: 'Return of the Jedi',
url: 'http://youtube.com/embed/5UfA_aKBGMc'
}
];
});
Let's hook up $scope.movies with our server.
Use Bower to add Restangular to your project
bower install --save restangular
Verify it adds it to app/index.html
app/scripts/app.jsangular .module('clientApp', [ 'ngRoute', 'restangular' ]) .config(function ( $routeProvider,
RestangularProvider ) {
RestangularProvider.setBaseUrl('http://localhost:3000'); ... ...
app/scripts/app.js.factory('MovieRestangular', function(Restangular) { return Restangular.withConfig(function(RestangularConfigurer) { RestangularConfigurer.setRestangularFields({ id: '_id' }); }); })
.factory('Movie', function(MovieRestangular) { return MovieRestangular.service('movie'); })
app/controllers/movies.js
.controller('MoviesCtrl', function (
$scope,
Movie
) {
$scope.movies = Movie.getList().$object;
});
yo angular:route movie-add --uri=create/movie
yo angular:route movie-view --uri=movie/:id
yo angular:route movie-delete --uri=movie/:id/delete
yo angular:route movie-edit --uri=movie/:id/edit
app/views/movie-add.html
app/scripts/controllers/movie-add.js
.controller('MovieAddCtrl', function (
$scope,
Movie,
$location
) {
$scope.movie = {};
$scope.saveMovie = function() {
Movie.post($scope.movie).then(function() {
$location.path('/movies');
});
};
});
app/views/movie-view.html
{{ movie.title }}
{{ movie.url }}
app/scripts/controllers/movie-view.js
.controller('MovieViewCtrl', function (
$scope,
$routeParams,
Movie
) {
$scope.viewMovie = true;
$scope.movie = Movie.one($routeParams.id).get().$object;
});
app/views/movie-edit.html
app/scripts/controllers/movie-edit.js
.controller('MovieEditCtrl', function (
$scope,
$routeParams,
Movie,
$location
) {
$scope.editMovie = true;
$scope.movie = {};
Movie.one($routeParams.id).get().then(function(movie) {
$scope.movie = movie;
$scope.saveMovie = function() {
$scope.movie.save().then(function() {
$location.path('/movie/' + $routeParams.id);
});
};
});
});
app/views/movie-delete.html
app/scripts/controllers/movie-delete.js
.controller('MovieDeleteCtrl', function (
$scope,
$routeParams,
Movie,
$location
) {
$scope.movie = Movie.one($routeParams.id).get().$object;
$scope.deleteMovie = function() {
$scope.movie.remove().then(function() {
$location.path('/movies');
});
};
$scope.back = function() {
$location.path('/movie/' + $routeParams.id);
};
});
Create: app/views/movie-nav.html
app/views/movie-view.html
{{ movie.title }}
{{ movie.url }}
app/views/movie-edit.html
app/views/movies.html
Create Movie
Title
URL
Operations
{{ movie.title }}
{{ movie.url }}
app/scripts/app.js.directive('youtube', function() { return { restrict: 'E', scope: { src: '=' }, templateUrl: 'views/youtube.html' }; })
.filter('trusted', function ($sce) { return function(url) { return $sce.trustAsResourceUrl(url); }; });
app/views/youtube.html
app/views/movie-view.html
{{ movie.title }}