Intro to AngularJS

Up and running with fundamentals

Heads Up

Girl Develop It is here to provide affordable and accessible programs to learn software through mentorship and hands-on instruction.

Some "rules"

  • We are here for you!
  • Every question is important
  • Help each other
  • Have fun

Introductions

Tell us about yourself.

  • Who are you?
  • What do you hope to get out of the class?
  • If you could make any website, what would it be?

You should have:

A Codepen account.

For coding at home, a text editor (Atom, Sublime Text)

Four Day Agenda

  1. Angular Basics + Best Practices
  2. Managing Data with Services, Forms
  3. Useful add-ons: UI-Router, UI-Bootstrap, testing
  4. Practice, Quick Detour into Angular 2

Day 1

  • Controllers, directives, filters
  • Data binding
  • MVC/MV*
  • Scope and $scope best practices

So WHAT is Angular?

  • Client-side Javascript Framework for Single Page Applications (SPAs)
  • Allows you to extends HTML
  • Data binding!
  • Easy to test
  • Handles it's own dependency injection

Also

  • Likes to own everything
  • You'll need to think about page refreshes, back button
  • Also consider performance
  • Use $scope.$watch and two-way data binding sparingly

index.html

<body ng-app="app">
<p>2 + 2 = {{2 + 2}}</p>
</body>
						

How Angular works

  • Each variable used in a view is added to a $watchers list
  • A digest loop checks for changes on page events
  • This is called "dirty checking"

Model View Whatever

Other Tools People Use

  • Handlebars (Server side view)
  • Backbone (non-opinionated)
  • Ember
  • React (View)

Directives

View components and logic

angular.module('app', []).directive('myTooltip', myTooltipFn);
<my-tooltip></my-tooltip>
<div my-tooltip="options"></div>
				

index.html

<body ng-app="app">
<h1>{{pageTitle}}</h1>
</body>
						

Built-in directives

  • ng-app
  • ng-if
  • ng-show/ng-hide
  • ng-click
  • ng-model
  • ng-change
  • ng-repeat
  • ng-controller

ng-if

              <button ng-if="changesEnabled">Edit</button>
            

ng-model

Two way data binding!

							<input type="text" ng-model="name"/>
Name: {{name}}
						

ng-click

							<a href="" ng-click="openModal()">See details</a>
						

ng-change

								Start Date:
<input ng-change="updateMinDate()" type="text" uib-datepicker/>
							

ng-repeat

								<table>
<tbody>
	<tr ng-repeat="account in accounts track by $index">
		<td ng-bind="account.name"></td>
	</tr>
</tbody>
</table>
								
							

Let's explore Codepen!

http://codepen.io/Sinetheta/pen/olBxp

Controllers

View logic and scope

Use with ng-controller directive, ng-view, or ui-view (with UI-Router - more on this later!)

app.js

              angular.module('app', []) .controller("menuController", ['$scope',
function($scope) { $scope.pageTitle =
"Angular Example Site"; }]);
              
            

index.html

<!DOCTYPE html><html ng-app>
<head><title>{{pageTitle}}</title></head>
<body>
	<div ng-controller="menuController">
		<h1>{{pageTitle}}</h1>
	</div>
	<script src="./app.js">
	</body>
</html>

						

Scope and $scope

  • An angular application can be made up of multiple modules, each with multiple controllers and directives
  • Unfortunately, since $scope is shared among all modules in an app, it is easy to pollute and overwrite values

'this' and 'as'

app.js

								angular.module('app', []) .controller("menuController", ['$scope',
	function($scope) { this.pageTitle =
	"Angular Example Site"; }]);
								
							

index.html

	<!DOCTYPE html><html ng-app>
	<head><title>{{pageTitle}}</title></head>
	<body>
		<div ng-controller="menuController as menuCtrl">
			<h1>{{menuCtrl.pageTitle}}</h1>
		</div>
		<script src="./app.js">
		</body>
	</html>

ng-repeat

								<table ng-controller="accountController as accountCtrl">
<thead>...</thead>
<tbody>
	<tr ng-repeat="account in accounts track by $index">
		<td ng-bind="account.name"></td>
	</tr>
</tbody>
</table>
							

Filters

{{ name | uppercase }}

Sam -> SAM

{{ startDate | date:'MM/dd/yyyy' }}

new Date() -> 04/26/2016

ng-repeat

								<table ng-controller="accountController as accountCtrl">
<th ng-repeat="tableLabel in accountCtrl.accountTableLabels">
{{tableLabel | uppercase}}</th>
<tbody>
	<tr ng-repeat="account in accounts track by $index |
accountCtrl.balanceOverZero">
		<td ng-bind="account.name"></td>
	</tr>
</tbody>
</table>
							

app.js

              angular.module('app', []).service("menuService", function() {
	this.pageTitle = "Angular Example Site";
})
.controller("menuController", ['$scope', 'menuService',
	function($scope, menuService) {
		$scope.pageTitle = "Angular Example Site";
}]);
              
            

index.html

							<!DOCTYPE html>
<html ng-app><head><title>{{pageTitle}}</title></head>
<body>
	<div ng-controller="menuController">
		<h1>{{pageTitle}}</h1>
	</div>
	<script src="./app.js">
	</body>
</html>
						

Codepen Practice!

Fork this codepen and use six directives you've learned: http://codepen.io/arilaen/pen/oxPwQq

Here's the list again (starred directives are required):

  • ng-app
  • ng-controller
  • ng-if
  • ng-show/ng-hide
  • ng-click
  • ng-model
  • ng-change
  • ng-repeat

Next time...

  • Make your own directives!
  • Services
  • Forms

Intro to Angular Part 2

Questions/thoughts before we begin?

Day 2

  • Recap of Basics
  • Create your own directives!
  • Forms

Recap: WHAT is Angular?

  • Client-side Javascript Framework for Single Page Applications (SPAs)
  • Allows you to extends HTML
  • Data binding!
  • Handles it's own dependency injection

Recap: Model View Whatever

http://www.techstrikers.com/AngularJS/angularjs-mvc-pattern.php

https://plus.google.com/+AngularJS/posts/aZNVhj355G2

Recap: Directives

View components and logic

angular.module('app', []).directive('myTooltip', myTooltipFn);

Element style

<my-tooltip></my-tooltip>

Attribute style

<div my-tooltip="options"></div>
				

Recap: Built-in directives

  • ng-app
  • ng-if
  • ng-show/ng-hide
  • ng-click
  • ng-model
  • ng-change
  • ng-repeat
  • ng-controller

Let's go over yesterday's codepen!

http://codepen.io/arilaen/pen/oxPwQq

Recap: Controllers

app.js

								angular.module('app', []) .controller("menuController", ['$scope',
	function($scope) { this.pageTitle =
	"Angular Example Site"; }]);
								
							

index.html

	<!DOCTYPE html><html ng-app>
	<head><title>{{pageTitle}}</title></head>
	<body>
		<div ng-controller="menuController as menuCtrl">
			<h1>{{menuCtrl.pageTitle}}</h1>
		</div>
		<script src="./app.js">
		</body>
	</html>

So How Do You Create YOUR OWN Directive?

There are two types:

  • Element:
    							<profile-section></profile-section>
  • Attribute:
    							<input type="number" model="accountCtrl.percentGoal" percent-mask />

Element directives

  • Placeholder for an HTML template
  • Simplest example:
    								<ng-include="./profile-section-template.html"></ng-include>
    							
  • This element directive JUST brings in the template, with no extra logic
  • Results in an extra AJAX request at runtime
  • Avoid this by making your own directives!

Attribute directives

  • Add an attribute (logic) to another HTML tag
  • Examples: ng-click, ng-model, etc.
  • Do not include templates

Both element and attribute directives...

  • Can include view logic, can even include a controller
  • Can have *isolate scope*

Code!

						angular.module('app', []).directive("profileSection", function() {
	return {
		restrict: 'E', //E for element, A for attribute!,
		templateUrl: './profile-section.html',
		scope: {},
		transclude: true //Has access to everything in parent scope - avoid!
	}
};
					

Code with template!

						angular.module('app', []).directive("profileSection", function() {
	return {
		restrict: 'E',
		template: '<div class="profile-section"><h2>Profile</h2></div>',
		scope: {}
	}
};

					

Now let's add variables to scope!

						angular.module('app', []).directive("profileSection", function() {
	return {
		restrict: 'E',
		template: 'Name: {{name}}, Age: {{age}}',
		scope: {
			name: '=name', //or '='
			age: '=age' //or '='
		}
	}
};

					

And now we can use our directive!

<table>
<tbody>
<tr ng-repeat="user in users">
<profileSection name="user.name" age="user.age"></profile-section>
</tr>
</tbody>
</table>
					
				

More Examples at Angular Docs

https://docs.angularjs.org/guide/directive

Your Turn!

Write your own directive in your codepen

Ideas:

  • A header
  • A footer
  • Menu
  • Link
  • Description (for a blog post, etc.)

More with directives

You can add logic via a controller:

	angular.module('app', []).directive("profileSection", function() {
		return {
			restrict: 'E',
			template: 'Name: {{name}}, Age: {{age}}',
			controller: 'ProfileController' // Angular manages dependencies and will find this with just a string!
			scope: {
				name: '=name', //or '='
				age: '=age' //or '='
			}
		}
	};
	

More with directives

Or more commonly, with a link function (more on this next class):

angular.module('app', []).directive("", function() {
	return {
		restrict: 'A',
		template: 'Name: {{name}}, Age: {{age}}',
		scope: {
			firstName: '='
			lastName: '='
		},
		link: function(scope, element, attributes) {
			scope.name = scope.firstName + ' ' + scope.lastName;
		}
	}
};
					

'=', '@', '&'

'=' is for two way binding

'&' is for one way binding (usually functions)

'@' is for text

	angular.module('app', []).directive("profileSection", function() {
		return {
			restrict: 'E',
			template: 'Name: {{name}}, Age: {{age}}',
			scope: {
				name: '='
				age: '@'
			}
		}
	}; // <profile-section name="user.name" age="20"></profile-section>
	

Tools for forms

  • ng-model: Use on inputs to keep track of updates
  • ng-submit: Runs when you submit a form
  • Don't just rely on ng-click - user can press enter to submit a form
  • Can review codepen for an example of this in practice

Optional: Save data to a service

  • Services can be shared across different controllers
  • Can also load data from/send data to back end, store in local storage, etc.
  • More on this next class

Adventure trip!

  • Choose your favorite destination for a group trip! Decide how many people can go.
  • Create a model for the travelers (Name, Age, Email, Photo, Has previously visited? Allergies? etc.)
  • Display who's going and # spots remaining
  • Create a traveler row directive with name, age, etc.
  • Add a form for people to sign up for the trip
  • Extra: Hide form when trip is full
  • Extra: Use two controllers and store data in a service

Day 3

  • Adventure trip!
  • Review Week 1
  • Services

Day 1

  • Controllers, directives, filters
  • Data binding
  • MVC/MV*
  • Scope and $scope best practices

Day 2

  • Create your own directives!
  • Forms

Codepen review! http://codepen.io/arilaen/pen/oxPwQq

Services

  • Singletons - only one instance is created
  • Can use built-in services ($http, $cookies)
  • Can create your own - store or share data
  • Lazily created - only made when needed

Making a service

							
angular.module('app', []).service("menuService", function() {
	this.pageTitle = "Angular Example Site";
})
.controller("menuController", ['$scope', 'menuService',
	function($scope, menuService) {
		$scope.pageTitle = "Angular Example Site";
}]);
							
						

index.html

							<!DOCTYPE html>
<html ng-app><head><title>{{pageTitle}}</title></head>
<body>
	<div ng-controller="menuController">
		<h1>{{pageTitle}}</h1>
	</div>
	<script src="./app.js">
	</body>
</html>
						

Built-in Services

  • $http
  • $cookies
  • $localStorage
  • $window + $document
  • $log
  • $state (external - comes with ui-router module)

$http

						
angular.module('app', []).service("todoService", ['$http',
function($http) {
	var service = this;
	this.getTodos = $http.get('http://jsonplaceholder.typicode.com/todos');
	this.todos = [];
	function init() {
		this.getTodos().then(function(data) {
			service.todos = data;
		});
	}
	init();
}]);
						
					

$http

						
angular.module('app', [])
.service("todoService", todoService)
.controller("todoController", ['$menuService',
function($menuService) {
	this.todos = menuService.todos;
}]);
						
					

What then?

Asynchronous vs. Synchronous Code

Most of your code is synchronous - runs sequentially

var data = [{id: 0, name: 1}];
console.log(data.name);

What then?

Asynchronous vs. Synchronous Code

Most of your code is synchronous - runs sequentially

						var data = [{id: 0, name: 1}];
						console.log(data.name);

Asynchronous Code + Promises?

For external calls, use promises and callbacks

						$http.get('/posts').then(function(result) {...})

$http

						angular.module('app', [])
.service("todoService", todoService)
.controller("todoController", ['$menuService',
function($menuService) {
	this.todos = menuService.todos;
	this.addTodo = menuService.addTodo;
	this.updateTodo = menuService.updateTodo;
	this.saveTodo = menuService.saveTodo;
}]);
						
					

Practice

Let's put it all together and use services with a form, in codepen!

http://codepen.io/arilaen/pen/oxPwQq

Day 4

  • Components
  • $scope.$watch
  • Review + Trip planning site!

Components

  • Introduced in Angular 1.5; big part of Angular 2
  • Type of element directive
  • In the future, Angular will be all components - no controllers, just components and attribute directives
  • MVComponent?

Components

						angular.module('app')
.component('heroDetail', {
  templateUrl: 'heroDetail.html',
  controller: HeroDetailController,
  bindings: {
    hero: '='
  }
});
						
					

$scope.$watch

Allows us to define our own two-way data binding!

						angular.module('app', [])
.controller("todoController", ['$scope',
function($scope) {
	$scope.hours = 10;
	$scope.cost = $scope.hours * 3;
	$scope.$watch(function(newValue, oldValue) {
		$scope.cost = $scope.hours * 3;
	});
}]);
						
					

Practice! Time to finish your trip apps! You can follow along with me here: http://codepen.io/arilaen/pen/oxPwQq

Next steps

  • Learn about Angular 2
  • Try out ui-router and ui-bootstrap
  • Create your own Angular app and deploy it on heroku with node and npm

Resources