In this section we will implement the communication layer for our application. It’ll handle
all the requests to/from our web server. Have no worries - we will create server application
in the next section!
Let’s create a Session resource. Since we have no backend part, we should stub
the data. We’ll use Angular Services. That’s easy: a service defines a
function, returning, say, an object. That object will be used every time you
call a service. And you may use not only objects - you may return functions,
constants or literally anything from your services.
We’ll return an object with two methods: get(account) and create(account).
Both methods will take an object, containing user account details - email,
password, and, in case of create(), name and password_confirmation, additionally.
You might’ve guessed already: the get(account) method will log the user in and
create(account) will register a new account for the user.
When you inject it into your controller, you may use it via
The thing here is that we want to keep user data somewhere to simulate a
database work. So when user “signs up”, he will have his data saved in the memory
not to loose it when changing a page. We’ll use another service for that purpose.
But contrary to our sessions service, this one will be used in the future and even
Now, here’s one more trick: we defined our Session factory in the ourStatsControllers module.
Why did we do this? Why not just use ourStatsApp module? This is done mostly to keep things
in one place, so everything related to controllers and UI processing is kept inside one module.
Doing so we can later separate our modules into separate files and keep our main application
module clean from unnecessary code (in terms of the whole application).
already! It is called ngCookies. And we’ll install it right now:
This one’s configuration is a bit more complicated. But just a bit: it needs
to be added to application dependency list:
the ourStatsControllers module:
Now we need to define our AccountData service. It’ll also require a ngCookies dependency:
And we need to modify our Session service a bit:
And now we can implement the controller to pick up the newly added service:
But here’s just one small detail: we need both Session and AccountData services to perform
similar actions - managing session. We can refactor our code to keep all the session management
tasks in one place - Session service:
Now our NewSessionCtrl could be refactored too:
Looks better, huh?
So now we have our first member of our Model layer. It works with stubbed data right now,
but we’ll be changing that later. It is not bound to the ViewModel, because the values
of our $scope.newAccount and $scope.existingAccount are constant and don’t depend on
the template. To change this, we need to modify our new_session.jade template:
Note the ng-model directive: it performs two-way data binding. It means, when user changes the
value of our, say, name input, the corresponding value inside controller, namely $scope.newAccount.name,
will also change. What’s more, when the value of $scope.newAccount.name will be changed from
will also be changed.
Now, what’s about the ng-submit directive. It is added to form tags only. And it works exactly as
you might’ve guessed: when form is submitted, the corresponding expression within that directive is called.
Making fake calls
Now that we have our stubbed signing in and up routines, we may redirect user to the right page
when he signed in or up successfully. This is the job for $location service. It’s available
in Angular core module, ng, so we don’t need to add any new module-wise dependencies.
Just use it in our NewSessionCtrl:
Here comes new refactoring-able piece of code: we now have our routes declared in both
ourStatsApp module and ourStatsControllers. So if we decide to change, let’s say,
route /new-session to /login, we will need to change it in both modules. We can easily
extract those URLs into a single service and use it in both ourStatsControllers
and ourStatsApp modules, because everything we define in ourStatsControllers will be
available in the ourStatsApp thanks to dependency injection. And since our URLs will
always be the same (except, maybe, the parametrised ones), we may define a constant
instead of factory:
Application startup phases
As you can see, there are a couple of entities you can create with Angular - we’ve already
dealt with controllers, factories, modules and constants. They all are slighty
different from each other and the difference lies under Angular startup process.
When your application “starts up” or initializes, there are two kingds of methods, which are
ran first: config and run. They are user-defined and your application can have more than just
one of those. Those methods define the initialization behaviour of your application. They both
can deal with dependency injection. But their run order is different: config blocks are executed
first, at the very beginning of the whole application initialization process. Thus you can inject
only providers($routeProvider for instance) and constants into config blocks.
Whilst run blocks can only handle instances(for example, $scope) and constants.
Since we have our routes defined at the config stage, we need to use constant to name our
routes. And then use them like this:
To show the difference in practice, let’s add the authentication verification. We now have our
stubbed account and session management service, so why not? Angular provides us with two options:
the resolve attribute for the $routeProvider.when() method
the $routeChangeStart event
The first approach is nice, but since we set up routes in the config section, we are not allowed
to use services. And that is the problem, because we’ve got our Session service, handling the
tasks we need. And one more drawback of this method: one should set it for each route, which requires
Handling $routeChangeStart event suits us, and what’s more interesting: it shows the use of run
section. But as a drawback to this, we’ll need the list of routes, which need to be checked. So
I modified the definition of Url constant like this:
A bit tricky, does not it? And here’s the handler for the $routeChangeStart event:
Other services and controllers are much like those we already have, so I’ll just put in the code
in the end of the page. The interesting thing here is the MockData service that I’ve used to keep
data, used while we have no server side.
And here’s the demo of what we’ve done up until now: