We are going to dive into Angular Controllers, ViewModels and Modules.
- Implement a Controller.
- Share data between a Controller and a View.
- Implement an Angular Module to namespace and contain Angular components.
- Show how Module dependencies can be defined.
Few important features of AngularJS are:
- two-way data binding (Done)
- separation of concerns (In this lesson)
- testability
- abstraction (Some in this lesson. More later)
We will be looking at Controllers, Views and Modules in this lesson. We covered Views and directives in the last lesson, Angular Views and Directives
Get AngularJS libraries.
bower install
At the end of the lesson we will have an app/controllers directory where the the controllers are defined.
There is a concept of a View Model in Angular. This View Model will allow a Controller to share Data with a View.
#####In Angular there are TWO ways to share data between an Controller and a View.
- First, and preferred is using the "Controller as" method. The View Model is an instance of the Controller.
- Second is to use
$scope
. The View Model is$scope
.
This is the recommended way to to share data. The View Model will be an instance of the Controller.
Create a pets.html
<!document html>
<html ng-app>
<head>
<script type='text/javascript' src='bower_components/angular/angular.js'></script>
</head>
<body>
</body>
</html>
Create a app/app.js
angular.module('petsApp', []);
Add the application name/module to the ng-app directive in the pets.html
...
<html ng-app='petsApp'>
...
This will name the Angular application, provide a namespace for it, 'petsApp', and a top level module. We'll learn about modules later.
Add a Controller file, app/controllers/petsController.js
(ƒ(angular){
// Constructor Function
function PetsController(){
this.pets = [{name: 'Rover', species: 'Dog', age: 7},{name: 'Milo', species: 'Horse', age: 3}, {name: 'Sh*tCa\
t', species: 'Cat', age: 11}, {name: 'Mertle', species: 'Turtle', age: 123 } ];
}
// The Controller is part of the module.
angular.module('petsApp').controller('PetsController', PetsController);
})(angular);
Lots of stuff here.
We are creating a Controller for pets. It's really just a Javascript Constructor Function. Later, we'll use it to create ONE instance of a PetsController.
Then we create an array of object literals, each one holding data about a pet. The controller instance we create in the view will have it's 'pets' property set to this array of pets.
Notice that we put all the code in an IIFE that get's passed the global angular variable. Passing in a global is just an optimization, JS doesn't need to search up though all enclosing scopes to look for a variable.
We do this so we can put private variables in this scope that will NOT pollute the global namespace.
We haven't yet created any private variables, but we may as time goes on
Update the pets.html to use this controller
...
<head>
<script type='text/javascript' src='bower_components/angular/angular.js'><\
/script>
<script type='text/javascript' src='app/app.js'></script>
<script type='text/javascript' src='app/controllers/petsController.js'></script>
</head>
<body ng-controller="PetsController as petsCtrl">
<h3>Pets</h3>
<br/>
<table>
<tr>
<th>Name</th>
<th>Species</th>
<th>Age</th>
</tr>
<tr ng-repeat="pet in petsCtrl.pets">
<td>{{ pet.name }}</td>
<td>{{ pet.species}}</td>
<td>{{ pet.age }}</td>
</tr>
</table>
</body>
Open this pets.html in the browser. You should see a table of pets.
First, we included the javascript files for the app, app.js, and the controller, app/controllers/pets_controller.js.
Then in the body
tag we created a ng-controller
attribute. We set this attribute to have a value that will make the one instance of the PetsController avaialble in the View. The name will be 'petsCtrl' in the view will refer to this ONE instance of the PetsController.
Add this to the PetsController, right above the angular.module line.
...
PetsController.prototype.totalPets = function(pet){
return this.pets.length;
};
PetsController.prototype.oldestPet = function(){
var candidatePet = this.pets[0];
this.pets.forEach(ƒ(pet){
if (pet.age > candidatePet.age) {
candidatePet = pet;
}
});
return candidatePet;
};
...
Here we create to methods on the controller.
Add this to the pets.html
<br/>
<span>Oldest pet: {{ petsCtrl.oldestPet().name }}</span><br/>
<span>Total number of pets: {{ petsCtrl.totalPets() }}</span>
This will use these two Controller methods in the View.
The ViewModel is shared between a Controller and a View. In this case $scope is the ViewModel.
- The ViewModel,
$scope
, is injected into the Controller. - The Controller can add or change a properties in the $scope and make them visible to the View.
In Angular, one must explicitly set a property on the ViewModel, $scope, in the Controller for it to become available in the View.
For example, in order to share a property between a Controller and a View one must set this property on the ViewModel, $scope.
In the Controller:
$scope.pet = {name: 'Rover', species: 'Dog', age: 7};
Is made available in the View:
<p> {{pet.name} is only {{pet.age}</p>
Let's refactor the code we've used in the previous lesson about Views and Directives into an Angular Controller.
-
Start with the code from the last directives lesson, directives_last.html.
-
Rename this html file to customers.html.
-
Create a application module for this customer's app in app/customers.js
-
Update the ng-app directive in the customers.html, ya know in the html tag.
-
Create a controller in the app/controllers/customersController.js
5.1 Create an array of customers in the controller, hint move it from the ng-init.
5.2 Create controller properties forsortBy
andreverse
. -
Update the body tag so we will create one instance of the CustomersController for the view. The view will refer to this instance
as
customersCtrl. -
Invoke the CustomersController.doSort method where needed. Yes, you must create this controller method.
-
Invoke the CustomersController.numOfCustomers method where needed. Yes, you must create this controller method.
The customers_done.html file will have the finished template.
This is like the $.ajax in JQuery.
Ajax HTTP Service