An interactive introduction to
AngularJS
What is AngularJS?
AngularJS is a structural framework for dynamic web apps, using HTML for templating and allows extending HTML's syntax to render custom built components.
Angular is what HTML would have been, had it been designed for applications
AngularJS is a front-end web application MVC framework
MVC - Model View Controller
Athough, Angular does behave a lot like MVVM - Model View ViewModel
AngularJS great for building SPAs
AngularJS splits up responsibilities into modules
Which makes it very testable
Unit Tests
- karma
- jasmine
E2E Tests
- protractor
What does
AngularJS provide?
Models
- A Model is a singleton defined by service
- Handles the business logic
- Model provides an excellent way to separate data and display
- are great for unit testing!
Templating
AngularJS uses HTML for templating
You can choose to use other engines like jade
( VIEW )
Controller
-
Acts as an interlayer between model and view, should be as thin as possible.
-
avoid business logic in controller
-
should not care about presentation or DOM manipulation.
Two Way Data Binding
Through scope
"Providers"
- Value
- Constant
- Factory
- Service
- Provider
Directives
Directives are special markers on a DOM element (such as an attribute, element name, comment or CSS class) that signals AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children
This deserves it's own presentation
Animations
Modules
AngularJS modules are collections of configuration and run blocks which get applied to the application during the bootstrap process
are containers for the different parts of your app
Routing
define routes, the view and controller that render when accessing that route
Let's make an app!
Create a static server
- Create a package json file
- install the express module
- create a server.js file
- setup express static middleware
to serve static files from public/ - commit
- tag as step1_server
- Make a new angular_tutorial git project
- create a public/ directory
- add html5 markup to index.html
- import angular from cdnjs
- start the server with nodemon
- test
- commit
- tag as step2_html5
HTML5 Angular App
Templating
using angular binding tags, display a javascript expression on the page
- Set the body tag as the app container using the ng-app directive
- Concatenate a string in h1: "Hello"+"Angular!"
- Add 2 + 3 in a div
- test
- commit
- tag as step3_templating
Templating
Code Samples
<!-- angular model binding -->
<div>
{{ "Hello"+"Angular!" }}
</div>
<!-- accepts any expression -->
<div>
{{ 2 + 3 }}
</div>
Models
- Create a text input and set the model name to "myModel" using the ng-model directive
Use the ng-model directive to declare a model
Models
Code Samples
<!-- set firstName model in html template -->
<input type="text" ng-model="firstName">
<!-- bind model value to template -->
<div>
{{ firstName }}
</div>
// set model in a controller
$scope.firstName = "Archer";
Two way data-binding
- Add the value of "myModel" to a new div
- test
- commit
- tag as step4_two_way_databinding
Using data binding tags, display the current value of myModel
Modules
- Set the value of the ng-app directive to "myApp"
- Create "js/myApp.js" and import the source file
- commit
- tag as step5_angular_module
Import a new external javascript file.
Create a new angular module, and set the body tag as the module container.
Modules
Code Samples
// creation uses a 2nd array argument to import dependencies
angular.module('myApp', []);
// retrieval has only one argument
var myApp = angular.module('myApp');
myApp
.config(function(){
// config
})
.run(function(){
// initialize
});
Controller
- Declare myController in myApp.js
- Inject the $scope dependency
- Attach a new model named myFirstName to $scope with your name as the value
- Add a new div and set the ng-controller directive to myController
- test
- commit
- tag as step6_controller
declare a controller named myController
on the myApp module
Controller
Code Samples
var myApp = angular.module('myApp');
myApp.controller('MyController', function(){
});
myApp.controller('MyController', ['$scope', function($scope){
});
$scope
- Move the text input and {{ myModel }} into the controller
- Set the model named myModel to $scope with an initial value of "Ready Player One"
- test
- commit
- tag as step7_scope
set the initial value of myModel in the controller
Move Controller
- Create and import "js/controllers.js"
- Access the myApp module in controllers.js
- Move myController to controllers.js
- test
- commit
- tag as step8_external_controller
move the controller into a separate file
Value
- Create and import "js/values.js"
- Access the myApp module in values.js
- Declare a Value named mainCharacter
set to "Archer" - Inject mainCharacter into myController
- add mainCharacter to the $scope and display it
- test
- commit
- tag as step9_value
Create an injectable Value
Value
Code Samples
myApp.value('mainCharacter', 'Archer');
Constant
- Create and import "js/constants.js"
- Access the myApp module in constants.js
- Declare a Constant named APP_VERSION
set to "v.0.1.0" - Inject APP_VERSION into the run method of myApp
- add APP_VERSION to the $rootScope and display it
- test
- commit
- tag as step10_constant
Create an injectable Constant
Constant
code samples
myApp.constant('APP_VERSION','v.0.1.0');
Factory
- Create and import "js/factories.js"
- Access the myApp module in factories.js
- Declare a Factory named CharacterVersionFactory
that injects mainCharacter and APP_VERSION
and returns the concatenated value - Inject CharacterVersionFactory into myController
- Attach the factory to the $scope and display it
- test
- commit
- tag as step11_factory
Create an injectable Factory
like a Value, except can use other services
Factory
Code Samples
myApp.factory('HelloWorldFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
},
sayGoodbye: function() {
return "Goodbye";
}
};
});
// inject in controller
function MyController($scope, HelloWorldFactory) {
$scope.greeting = HelloWorldFactory.sayHello();
}
Service
- Create and import "js/services.js"
- Access the myApp module in services.js
- Declare a Service named BookService
define a private array named books with data
and declare two methods, getBooks and getBook - Inject BookService into myController
- Attach books to $scope and display it
- test
- commit
- tag as step12_service
Create an injectable Service
like a Factory, except returns a service by invoking a constructor
Service
Code Samples
myApp.service('HelloWorldService', function() {
this.sayHello = function() {
return "Hello, World!"
};
});
function HelloWorld2() {
this.sayHello = function() {
return "Hello, World!"
};
}
myApp.service('HelloWorld2Service', HelloWorld2);
function HelloWorld3withDeps( $http ) {
this.sayHello = function() {
return "Hello, World!"
};
}
myApp.service('HelloWorld3withDeps', ['$http', HelloWorld3withDeps]);
ng-repeat
- Convert the div.books into a ul tag
- Add the ng-repeat directive to iterate over books
- Add li.book>h4.book_title and li.book>p.book_author
- test
- commit
- tag as step13_ngRepeat
Use the ng-repeat directive to render each book
ng-repeat
Code Samples
<div ng-repeat="n in [42, 43, 44, 45]">
{{n}}
</div>
<div ng-repeat="book in books">
<h4>{{ book.title }}</h4>
<p class="book_author">{{ book.author }}</p>
</div>
<div ng-repeat="movie in MovieService.getMovies()">
<p>{{ movie.title }}</p>
</div>
ng-click
- Make books a public property, refactor
- Add an addBook method to BookService
- Instantiate a new literal from the book that's passed in
- Refactor myController to bind $scope.BookService
- Refactor the view to use BookService.books
- Create a form, a button, and add the ng-click directive
- Clear the new_book model after adding it
- test, commit
- tag as step14_ngClick
Use the BookService to add a new book
ng-click
Code Samples
<button type="button" ng-click="alert('hello world);">Hello World</button>
<button type="button" ng-click="BookService.addBook(new_book);">Add Book</button>
Provider
- Create a new server api/ endpoint that returns movies
- Create and import "js/providers.js"
- Access the myApp module in providers.js
- Create a new provider named Movies
- Configure the endpoint url in myApp config
- $scope.Movies -> Movies provider in myController
- Display all movies in the view
- test
- commit
- tag as step15_provider
Create an injectable and configurable Provider
It is the most verbose with the most abilities, but for most services it's overkill.
test!
sanity check!
Provider
Code Samples
myApp.provider('HelloWorld', function() {
this.name = 'Stranger';
this.setName = function(name) {
this.name = name;
};
this.$get = function() {
var name = this.name;
return {
sayHello: function() {
return "Hello, " + name + "!";
}
}
};
});
// configurable, note 'HelloWorldProvider' in config
myApp.config(function(HelloWorldProvider){
HelloWorldProvider.setName('Angular World');
});
// inject in controller
function myController($scope, HelloWorld) {
$scope.greeting = HelloWorld.sayHello();
}
Filters
- Apply a filter to the movies expression in ul.movies
- display only movies released in 1983
- test
- commit
- tag as step16_basic_filter
Filter only movies released in 1983
Custom Filters
- Create and import "js/filters.js"
- Access the myApp module in filters.js
- Apply a filter named beforeYearFilter to the movies expression in ul.movies
display only movies made after 1983 - test
- commit
- tag as step17_custom_filter
Create a custom Filter for movies released after 1983
Model Bound Filters
- Apply a filter to the books expression in ul.books
- display only books that match a user inputted title
- Add a new input[ng-model="searchBookTitle"]
- Bind the ng-filter value to searchBookTitle
- test
- commit
- tag as step18_model_bound_filters
Create a Filter that's matches user input to book titles
Filters
Code Samples
<ul class="books" ng-repeat="book in books | filter:year=1983">
<ul class="books" ng-repeat="book in books | filter:searchBookTitle">
Ordering Filters
- Apply an additional filter to the books expression to sort by title
- test
- Apply an additional filter to the movies expression to sort by year in reverse order
- test
- commit
- tag as step19_orderBy
Order book's by title, and reverse order movies by release date
Ordering Filters
Code Samples
<ul class="books" ng-repeat="book in books | orderBy:'title'">
<ul class="books" ng-repeat="book in books | filter:searchBookTitle | orderBy:'-year'">
Routing
- Import the ngRoute module from http://cdnjs.com/libraries/angular.js/
- Inject the routeProvider into the myApp module
- configure 4 routes, /, /books, /movies, /other
- create 2 directories views/ and controllers/
- create 4 new views, and 3 new controllers
- include the new js controller files into index.html
- test, commit
- add 4 navigation links
- test, commit
- tag as step20_routing
Inject and Configure $routeProvider
and split the views and controllers into separate files
Routing html5 mode
- Enable $locationProvider.html5Mode in myApp config
- set requireBase option to false
- refactor the nav link urls
- test, commit
- tag as step21_routing_html5_mode
Inject $locationProvider to enable html5mode to use prettier urls
Default Route
- Add $routeProvider.otherwise to the myApp config
- configure it to render a 404.html template
- create a simple 404.html page
- test
- update server.js to render the index.html file by default
- test
- commit
- tag as step22_default_route
Use $routeProvider.otherwise to set a default 404 route
fails!
RouteProvider
Code Samples
$routeProvider
.when('/', {
templateUrl : 'views/default.html'
})
when('/books', {
templateUrl : 'views/books.html',
controller : 'BooksController'
});
Animation
- Import the ngAnimate module from http://cdnjs.com/libraries/angular.js/
- Create and import the css/animations.css file
- Copy Pasta the following css source
Animate the changing of views using ngAnimate
Animation
animations.css
.ng-enter {
transition-delay: 0.5s;
transition:0.5s linear all;
opacity:0;
}
.ng-enter.ng-enter-active {
transition-delay: 0.5s;
opacity:1;
}
.ng-leave {
transition:0.5s linear all;
opacity:1;
}
.ng-leave.ng-leave-active {
opacity:0;
margin-left:20px;
}
.fade.ng-leave {
animation: my_fade_animation 0.5s linear;
-webkit-animation: my_fade_animation 0.5s linear;
}
@keyframes my_fade_animation {
from { opacity:1; }
to { opacity:0; margin-left:20px; }
}
@-webkit-keyframes my_fade_animation {
from { opacity:1; }
to { opacity:0; margin-left:20px;}
}
Animation
- test routes
- test books
- commit
- tag as step23_animation
Resources
Angular guide https://docs.angularjs.org/guide/scope
Providers https://docs.angularjs.org/guide/providers
ngRepeat https://docs.angularjs.org/api/ng/directive/ngRepeat
ngAnimate https://docs.angularjs.org/api/ngAnimate
$routeProvider https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
Interactive Intro to AngularJS
By Jon Borgonia
Interactive Intro to AngularJS
Intro
- 2,991