Series: Introduction to the MEAN Stack

After the last time we saw AngularJS only superficially, I want to introduce you today how you can use AngularJS to use a REST API.

For this purpose we use the REST API, which we have created in the article about Baucis. We add only a static file server to the example in the penultimate line so that we can output HTML, CSS, and JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var mongoose = require ‘mongoose’ 
var baucis = require ‘baucis’ 
var express = require ‘express’ mongoose. connect ‘mongodb: // localhost: 27017 / todo-db’ 

var TodoSchema new mongoose. Schema {
title { type : String default  ,
completed { type : Boolean default false 

mongoose. model ‘todo’ , TodoSchema 

baucis. rest {
singular ‘todo’ ,
plural ‘todos’ 

express )
use ‘/ api’ , baucis )
use( Express. Static ( __dirname  // new line
listen 1337 ‘127.0.0.1’ ;

Remember to install Mongoose, Baucis and Express, as well as launch the Node server and MongoDB. Also AngularJS should you again with Bower install.

After this preparation we can now begin with the example. Like Node, AngularJS is also divided into several modules. One of these is $ http, which allows you to perform HTTP requests, which is part of the core modules of AngularJS. This means that it is automatically installed with AngularJS. Another module with which you can perform HTTP requests is $ resource. It is based on $ http and is directly for use with REST APIs. It is also developed by the AngularJS team, but must be installed additionally. I would like to introduce you to another AngularJS module as a $ resource: Restangular, Restangular is very similar to $ resource, but offers more comfort and flexibility. It is not developed by the AngularJS team, but by Martin Gontovnikas. You install it with the following command:

1
$ bower install restangular

If you have watched the terminal carefully or bower_components look in your folder, you will find that you have downloaded another framework called Lo-Dash in addition to Restangular . Here we see one of the reasons why we use Bower: Sometimes different frameworks (or modules / components) depend on each other. With package managers like Bower and npm, we do not have to worry about these dependencies and save on work. I will not explain Lo-Dash at this point, since we will not use it, but it is a very useful little framework that simplifies the use of objects, arrays, strings, and the like. You may want to sniff the documentation of Lo-Dash to find out more.

You may smoke your head with the many frameworks and you see it as a bad practice to use and install too many frameworks. Something worry is, of course, appropriate, but these are really useful and very small frameworks. AngularJS may initially be a very large framework, but on the other hand it reduces your own self-written code considerably. If the file size of the frameworks disturb, then you are told that the biggest file size problems are still caused by pictures on web pages. As long as you do not optimize your images synonymous and thoroughly compressed, you should not yet (or few) thoughts about JavaScript files make. The later you all your code minified and packaged in a file – of which I go now;)

Now that we have all the necessary resources for our webapp, I show you in one go our client, which I owed the better readability owed completely in a single index.html :

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<! doctype html> 
html ng-app “todoApp” > 
head > <! – loadscripts -> 
script src “./bower_components/angular/angular.js” > < script > 
script src “./bower_components/lodash/dist/lodash.js” > < script > 
script src “./bower_components/restangular/dist/restangular.js” > < script > 

<! – create angular app – >
script >
angular
.module ( ‘todoApp’, [ ‘restangular’])
config (function (RestangularProvider) {
RestangularProvider.setRestangularFields ({
id: ‘_id’
});
})
.Controller ( ‘TodoController’, function ($ scope, Restangular ) {

$ scope.todos = [];
Restangular
.all ( ‘api / todos’)
.getList ()
.then (function (todos) {
$ scope.todos = todos;
});

$ scope.create = function () {
$ scope.todos
.post ({title: $ scope.newTodo})
.then (function (todo) {
$ scope.todos.push (todo);
});
};

$ scope.delete = function (todo, index) {
todo
.remove ()
.then (function () {
$ scope.todos.splice (index, 1);
});
};

});
script > 

<! – add style for completed todos -> 
style >
.completed {
color: green;
}
style > 
head > 
<body > 

<- create view: first a form to create new todos, then show a list of existing todos -> 
div ng-controller “TodoController” > 
form >
New Todo:
input type “text” ng-model “newTodo” > 
button ng-click “create ()” > Add < button > 
form > 

ul > 
<li ng-repeat “todo in todos”ng class “{completed: todo.completed}” >
{{}} todo.title
button ng-click “delete (todo, $ index)” > Remove button > or mark as completed:
input type “checkbox” ng-model “todo.completed” ng-change “todo.put ()” > 
li > 
ul > 
div > 

<body > 
<html >

Let’s go through the code step by step. In the htmlelement, we ng-app used the attribute as in the last article . This time we added the value todoApp . If we want to use additional modules like Restangular, then we need to assign a module directly to an AngularJS app. This is done at a later time with the string todoApp.

In the next section, we include AngularJS, Lo-Dash, and Restangular. As far as nothing unknown. In productive use I would put the scripts to the end of the HTML document, but for reasons of explanation I have brought the whole logic forward. Now begins the exciting section.

With the following code lines we create an AngularJS app called todoApp and tell her that it depends on Restangular:

1
2
      angular
module ‘todoApp’ ‘restangular’ )

This is followed by a configuration section in which individual modules can be configured before their use. In this case, we change a setting for Restangular. Restangular assumes that the REST API data has a idfield per document . However, as we know, this field is called MongoDB _id. So we have to change this setting. At this point, we also see dependency injection for the first time. RestangularProvider must be called RestangularProvider! If the parameter is different, we do not get the RestangularProviderobject! For AngularJS the names of parameters are important!

1
2
3
4
5
        , config function ( RestangularProvider {
RestangularProvider. setRestangularFields {
id ‘_id’ 

)

We then create a controller. The controller receives a name so that it can be assigned to a view later. We also inject a $scope– and a – Restangularobject. Dependency injection is used again here. If we write the parameters with a different name, we do not get our desired objects. In addition, the order of the parameters does not matter. Whether we  write $scope or Restangularwrite is irrelevant. Restangular makes us easier to use our REST API. But what is it   $scope$scope is the link between View and Controller, which allows two-way data binding. All data that is $scopeassigned to the object is accessible in the controller and the view. In other words, the $scopeobject holds our model.

1
        , controller ‘TodoController’ function ( $ scope , Restangular {

We now know that the $scopeobject gets our model and that we get the data of our model with Restangular via our REST API. This realization will be implemented in the next step. First, we name our model as a todosfield on the $scopeobject. It is initially an empty array. The array is now filled with real data. We say Restangular the URL to our REST API and the Collection ( ) and then request with  all available Todos. Then you see the function , which is a special feature. The object which/api/todosgetList()then()getList() is not our actual data. This is not possible because HTTP requests are asynchronous. If you know AJAX, you already know this, after all, the “A” is asynchronous. What we are back is a so-called promise . This is a widely used concept in AngularJS. However, it is not specific to AngularJS and can, for example, also be used in a node. A promise helps us to write asynchronous code more literally. In this case is  part of the Promise API. The callback  is received as soon as the promise has been met. In other words, the callback  is executed when we receive our Todos. The Todos are handed over to the callback, so we get themthen()then()then()$scope.todosArray. But beware: The Todos we receive are not exactly our Todos. When you  look at them, you see that they have much more fields and functions. These are Restoudangular extended versions of our Todos! This allows us to better deal with the data later.console.log

1
2
3
4
5
6
7
          $ scope. todos 
Restangular
all ‘api / todos’ )
getList )
then function ( todos {
$ scope. todos = todos 
;

Since we now have our Todos, let us change them. Our client offers the possibility to create new Todos and delete existing ones. For this reason, we create a function for this task in our controller: createand delete. We also assign these to the $scopeobject so that they can be called later from the view. In the createfunction we take our existing Todos and add  a new Todo. (Remember that our Todos have been expanded by Restangular , which is an extension that allows us to create new Todos quickly.) You see a new model named  on thepost()post()newTodo$scope, which we have not mentioned so far. This is a single string from a text input field, which we later define in the view. We get a promise from the function again, after all, the creation of new data via the REST API is asynchronous as is the retrieval of existing data. If our new Todo was successfully transferred, the promise is fulfilled and the callback is  called by, in which we  add our new Todo . This step is necessary for AngularJS to know that the data has changed. The function is very similar, but it refers to a single Todo and not to the entire array. The function also has a second parameterpost()then()$scopedeleteindex, which however only serves to make deleted Todo in the array easier to find.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
          $ scope. create function {
$ scope. todos
post { title : $ scope. newTodo )
then function ( todo {
$ scope. todos . push ( todo 

$ scope. delete function ( todo , index{
todo
remove )
then function {
$ scope. todos . splice ( index 

;

A short CSS section follows, in which only one style has been fixed. Elements with the class completed are to receive a green text. So we can distinguish between completed and unsolved deaths.

Now just follow our view. The view sits in an divelement, which we TodoController assign to ours . In this way, we can use the data and functions that the controller exposes over $scope in the view. The view consists of two parts: a form for creating new Todos and a list for displaying and editing existing Todos. The form consists essentially of a text field whose value newTodo is bound to the model , and a button that createcalls the controller’s function at a click.
The list looks a bit more complicated. A single lielement has been defined in the list that ng-repeat="todo in todos" begins with . It is a directive which provides theliElement as many times as there are entries in the model todos . Within li , a single Todo can be todo referenced. In addition, the lielement contains the section ng-class="{ completed: todo.completed }". This automatically sets the CSS class completed to the lielement, if the corresponding one has todothe value true in the field completed ! If this is not the case, the class is not set. Through two-way data binding this check happens at any time if the value changes! In the lielement, we {{todo.title}} first display the actual Todo via the placeholder . This is followed by a button, which deletecalls the function of the controller at a click . You see here the use of a special variable called$index, It is generated automatically by AngularJS and describes the index of todo within the todosarray. The following is a check box whose value is directly completed linked to the field . If the checkbox is used, the value changes true to false and vice versa. The directive ng-change allows us to be informed about a change so that we todo.put() can store it with our REST API.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    Div ng-controller “TodoController” > 
form >
New Todo:
input type “text” ng-model “newTodo” > 
button ng-click “create ()” > Add button > 
form > ul > 
li ng-repeat “todo in todos” ng- class “{completed: todo.completed} ” >
{todo.title}}
button ng-click “delete (todo, $ index)” > Remove button > or mark as completed:
input type “checkbox” ng-model “todo.completed” ng -change “todo.put ()” > 
li > 
ul > 
div >

Now test the app at http://127.0.0.1:1337/index.html . Set Todos on, kill Todos, mark them as done. You see that every action in the GUI is reflected. Look between again and again on http://127.0.0.1:1337/api/todos and you see that the data are equally reflected in the REST API. Opens between another browser and you can see the latest data.

Our finished web application

This ends my introduction to the MEAN stack. It was certainly incomplete and incomplete, but you could quickly gain experience in a variety of different technologies. They should serve as inspiration and a basic understanding. However, it takes much more effort to gain a deeper understanding of the MEAN stack. If you need further information or questions, just write in the comments.

I hope I could provide you with my article series a small overview of the MEAN stack.


0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: