AngularJS
AngularJS is JavaScript-based front-end web application framework mainly maintained by Google for developing single-page web applications.
Links
- https://angularjs.org/
- https://en.wikipedia.org/wiki/AngularJS
- Book Pro AngularJS, Pro AngularJS Source Code
Get AngularJS
You can download if from their site https://angularjs.org/ or get the AngularJS Googles CDN link to acess it directly from your HTML files
Simple example
Simple birthday list
<html ng-app="myFirstApp">
<head>
<title>My First App</title>
<link rel="stylesheet" href="bootstrap.css">
<link rel="stylesheet" href="bootstrap-theme.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script>
// for demo we put in some hard coded values here
var myInitialModel= {
people: [
{ FirstName:"Thomas", Name:"Tom", birthYear:1965},
{ FirstName:"John", Name:"Doe", birthYear:1960},
{ FirstName:"Jane", Name:"Doe", birthYear:1970},
{ FirstName:"Child", Name:"Baby", birthYear:2016},
]
};
// your angular app with dependency injection
var myFirstApp=angular.module("myFirstApp", []);
myFirstApp.filter("adultsOnly", function() {
return function(people, scope) {
var result=[];
people.forEach(function(person) {
if(scope.calcAge(person.birthYear)>=18)
result.push(person);
});
return result;
}
//return $scope.calcAge(person.birthYear)>=18;
});
// controller with code to do something with the model
myFirstApp.controller("MyFirstController", function($scope) {
$scope.myModel=myInitialModel;
$scope.calcAge = function (year) {
return new Date().getFullYear()-year;
};
$scope.isEmpty=function() {
return typeof($scope.myModel.people)=='undefined' || $scope.myModel.people.length==0;
};
$scope.averageAge=function() {
if($scope.isEmpty())
return 0;
var ln=$scope.myModel.people.length;
var sm=0;
$scope.myModel.people.forEach(function(p) {
sm=sm+$scope.calcAge(p.birthYear);
});
return sm/ln;
};
$scope.addUser = function(newName, newFirstName, newBirthYear) {
if($scope.isEmpty()) {
$scope.myModel.people=[];
}
var tmp={ FirstName:newFirstName, Name:newName, birthYear:newBirthYear};
$scope.myModel.people.push(tmp);
};
});
</script>
</head>
<!-- The view is plain HTML, we need to attach the controller to an element so its code is available here in the view-->
<body ng-controller="MyFirstController">
<h1>People List</h1>
<!-- Standard HTML form, calls addUser method of the controller once you hit the button-->
<h2>Add new</h2>
<div>
First Name: <input class="form-control" ng-model="newFirstName" />
Name: <input class="form-control" ng-model="newName" />
Birth Year: <input class="form-control" ng-model="newBirthYear" />
<button class="btn" ng-click="addUser(newName, newFirstName, newBirthYear)">Add</button>
</div>
<!-- Hide HTML elments based on controller logic-->
<div ng-hide="isEmpty()">
<h2>List of all people</h2>
<!-- This shows how to call a function in the controller and print its result-->
Average age of people in list: {{ averageAge() }}
<!-- Stadard HTML table, the rows are create automatically by ng-repeat reading the model-->
<table class="table">
<tr>
<th>Name</th><th>First Name</th><th>Age</th>
</tr>
<tr ng-repeat="onePerson in myModel.people | adultsOnly:this">
<td>{{onePerson.Name}}</td>
<td>{{onePerson.FirstName}}</td>
<td>{{calcAge(onePerson.birthYear)}}</td>
</tr>
</table>
</div>
</body>
</html>
Now lets see how to split all that into different files and go into some details
Controller
You have a block of HTML. Inside that block you want Angular to change some of the HTML. The code that will be responsible for that is the controller.
Here happens the magic
</div>
The controller code can (and should) be in its own file. Syntax of the very first row is slightly different compared to the all in one file variant. We first need to get the module by name (leave out the dependencies parameter). This .js file can be include like any other js file from the HTML with the script element.
...
The filter code also should go into its own file.
return function(people, scope) {
// ...
}
};
The filters can also go into another module than "myFirstApp" and can be used my multiple modules.
return function(people, scope) {
// ...
}
};
In this case we also need to declare a dependency to the new module
The view (the HTML) should also be separated files. The can be included with
Filter
An AngularJS filter takes some values and returns other values. It may format values, sort values, add extra values, or even filter out values (the only case where an AngularJS filter actually really filters). There are predefined filters and you can write your own ones.
Turn a number into a formated currency
Price: {{myModel.price | currency:'€' }}
(Real filter) and sort
Custom filter
return function(items) {
// return something based on items
}
Here are more filters [[ https://docs.angularjs.org/api/ng/filter | More AngularJs filter ]
You can also use those filters in your own ones if you have a dependency on $filter
return function(items) {
$filter("limitTo")(...);
}
Filters can be chained together, separated with | and are executed from left to right
Visibility
The CSS class of an element can be the result of a function call
And ng-show / ng-hide can even hide elements based on the result of a function call
<div ng-hide="bar()">
Click events
Do something when element is clicked
constant
You can add constants to the module for later use
.module('myFirstApp', [])
.constant("myURL", { "url": "http://localhost", "port": "80" })
.controller('MyFirstController', function (myConfig) {
// ...
});
Services
A Singelton that holds functions and data. Put that into a file called foo.js
.factory("myFirstService", function() {
var data1=0;
var data2=0;
return {
myFunction: function(bar) {
...
}
};
});
If you want to use that service you have to include the file like this <script src="foo.js"></script>
And in the module where you want to use the service, name the module where you did put your service (not the service itself) it as dependency
and you can pass in the Service myFirstService as an parameter