Show navigation
Welcome!
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
Agenda — Day 1
- Introductions
- Overview of MVC patterns
- Overview of a basic Angular app
- Built-in Directives and Expressions
Agenda — Day 2
- Controllers & $scope
- Dependency Injection
- Beyond the Basics
- Angular 2.0
Introductions
Tell us about yourself.
- Who are you?
- What do you hope to get out of the class?
- Which of your web projects are you most proud of?
What is AngularJS?
- A client-side JavaScript framework for extending HTML in small → large apps
- Initially released in 2009 by Google
- Used in production by Google, Virgin America, HBO, msnbc, Nike, Urban Outfitters, & more
- Known for data-binding, directives, dependency injection, & more
- Falls within the family of MV* frameworks, and is often compared to Ember.js, Backbone.js, & React
What is a MV* framework?
- A variation of an MVC (Model View Controller)
- Model — a type of data to model, like a user, account, photo, or note
- View — the markup & templates for the UI
- Controller — handles input & updates state of model
- MVC, MVVM, MVVMCS, ...
What is a MV* framework?
Image Credit: Wikimedia
What is a MV* framework?
- Main features are some combination of routing, data binding, templates/views, models & data access
- Can be client- or server-side, and not specific to JavaScript
What type of MV* is Angular?
- There's much debate on what exactly Angular is
- Angular has evolved since release, and developers implement it differently
- Many agree that it is an MVW (Model View Whatever)
Why Use Angular?
- Easy to get up and running
- Code organization
- Speedy websites
- Unit testing
- Many, many resources
An example Angular App
A basic todo list app
The app's markup
- You'll notice {{ }} and attributes beginning with ng-
- Those are the key components of an Angular View!
Including Angular
Download and serve local file
<script src="js/angular.min.js"><script>
OR
Use a content distribution network for a cached file
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
Built-In Directives
The Angular library looks for these attribute in your markup to know it should render Angular code
<body ng-app>
<h1>Hello World!</h1>
</body>
ng-app is a required directive used to identify the root element and determine scope
Expressions
A way to insert data into html via a JavaScript string, number, object, or array
<body ng-app>
<p>I have {{ 1 + 2 }} apples</p>
<p>My cat's name is {{ "Admiral " + "Snuggles" }}</p>
</body>
Exercise
- Download the demo files
- Open exercises/hello-world/hello-world.html in your text editor
- Import the Angular library
- Assign your root element with ng-app
- Include html with a few string & number expressions
Two-Way Data Binding
The ng-model directive binds the value of an input, select, or textarea to an object that can be used in an expression
<body ng-app>
<label>Name:</label>
<input type="text" ng-model="yourName">
<hr>
<h1>Hello {{yourName}}!</h1>
</body>
Two-Way Data Binding
Expressions can be inserted as the value html attributes as well as text within html tags
<body ng-app>
<label>Name:</label>
<input type="text" ng-model="user.status">
<hr>
<h1 class="status-text-{{user.status}}">Your status is: {{user.status}}!</h1>
</body>
Exercise
- In hello-world.html, within your ng-app, add the markup for a form input field
- Also add the markup for a heading
- Bind the value of the input to text within your heading tags by using ng-model
- Try to add a few more data-bindings with ng-model!
More Built-In Directives: ng-repeat
ng-repeat is Angular's way of looping
<body ng-app>
<ul>
<li ng-repeat="item in ['Sal', 'Jo', 'Amir', 'Maria']">
{{item}} is my friend.
</li>
</ul>
</body>
More Built-In Directives: ng-if
ng-if is Angular's if statement
<body ng-app>
<p ng-if="'Sal' === 'Sal'">True!</p>
<p ng-if="'Sal' === 'Jo'">False!</p>
</body>
More Built-In Directives: ng-show/ng-hide
ng-show & ng-hide toggle an element's display based on value
<body ng-app>
<p ng-show="5> 2">Five is greater than two.</p>
<p ng-show="2> 5">Two is greater than five.</p>
</body>
Note: if the value of ng-show evaluates to false, the element will still live in the DOM
Exercise
- In hello-world.html, within your ng-app, use ng-repeat to loop through an array of your favorite TV shows, and display each one on the page
- Use ng-show/ng-hide or ng-if to conditionally display an image of your favorite celebrity
More Built-In Directives: ng-init
ng-init sets an initial value
<head>
<!-- add icon font library -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
</head>
<body ng-app>
<nav ng-init="isOpen=false" class="mobile-nav">
<button><i class="fa fa-bars"></i></button>
<ul ng-show="isOpen">
<li>Home</li>
<li>About</li>
<li>Blog</li>
</ul>
</nav>
</body>
More Built-In Directives: ng-click
Angular's click listener
<body ng-app>
<nav ng-init="isOpen = false" class="mobile-nav">
<button ng-click="isOpen = !isOpen">
<i class="fa fa-bars"></i>
</button>
<ul ng-show="isOpen">
<li>Home</li>
<li>About</li>
<li>Blog</li>
</ul>
</nav>
</body>
Bonus! Angular will make your ng-click elements work with the keyboard too.
More Built-In Directives: ng-class
ng-class conditionally adds a class based on value
<body ng-app>
<nav ng-init="isOpen = false" class="mobile-nav">
<p ng-class="{'highlight': isOpen}">My Menu</p>
<button ng-click="isOpen = !isOpen">
<i class="fa fa-bars"></i>
</button>
<ul ng-show="isOpen">
<li>Home</li>
<li>About</li>
<li>Blog</li>
</ul>
</nav>
</body>
More Built-In Directives: ng-class
Here's another example:
<body ng-app>
<nav ng-init="isOpen = false" class="mobile-nav">
<button ng-click="isOpen = !isOpen">
<i class="fa" ng-class="{
'fa-caret-square-o-down': !isOpen,
'fa-caret-square-o-up': isOpen}">
</i>
</button>
<ul ng-show="isOpen">
<li>Home</li>
<li>About</li>
<li>Blog</li>
</ul>
</nav>
</body>
Exercise
- In hello-world.html, within your ng-app, add a new section or div where you set a value to true or false with ng-init
- Within that section/div, add a button with an ng-click directive that toggles the ng-init value
- Use ng-show or ng-hide to show/hide an image of your pet (or your favorite animal) on click of your button
Note!
It's good to know how ng-init works, but usually you'll use a controller for that purpose
Before we talk about controllers, let's talk about modules!
Modules
- Where we write pieces of the app and define dependencies
- Module names are bound to ng-app directives
(function(){
angular.module('myApp', []);
})();
<body ng-app="myApp">
<p>I have {{ 1 + 2 }} apples</p>
<p>Our President is {{ "Barack " + "Obama" }}</p>
</body>
Controllers
- They're where most of the app's functionality comes from
- They control the data that passes through
- They're regular JavaScript Objects
- There can be more than one controller in an app
Controllers
in app.js
(function(){
angular
.module('myApp', [])
.controller('MainController', function(){
this.cat = cat;
});
var cat = {
name: 'Ms. Whiskers',
age: 9,
eyes: 'blue'
};
})();
Controllers
in index.html
<body ng-app="myApp">
<section ng-controller="MainController as mainCtrl">
<p>My cat's name is {{mainCtrl.cat.name}}</p>
<p>She has {{mainCtrl.cat.eyes}} eyes and she's
{{mainCtrl.cat.age}} years old.</p>
</section>
</body>
The scope of the controller is only within the section element!
Exercise — Part 1
- In recipe-app/app.js, within the closure, create a module called 'recipeApp', a controller called 'RecipeController', and a variable called 'recipe'
- Set the recipe var as an object with a few different properties, like 'name', 'ingredients', 'prepTime', 'cookTime', and 'directions'
- Try to set one of these properties (like 'ingredients') as an array
- Add two or three new properties as booleans, like 'isVegan', 'isGlutenFree', or 'isPaleo'
- Set the recipe object as a property of the controller, using the 'this' keyword
Exercise — Part 2
- In recipe-app/index.html, add an ng-app directive with the value of "recipeApp", and an ng-controller directive with the value of "RecipeController as recipeCtrl"
- Include a few expressions referencing properties of the recipe object
- Use ng-repeat to iterate over one of your array properties in the recipe object
- Use ng-if or ng-show to conditionally display your boolean properties
Controllers
Often your data will be stored in an array, rather than a single object like we've seen so far
(function(){
angular
.module('myApp', [])
.controller('MainController', function(){
this.cats = cats;
});
var cats = [
{
name: 'Ms. Whiskers',
age: 9,
eyes: 'blue'
},
{
name: 'Melvin',
age: 1,
eyes: 'green'
},
{
name: 'Tootsie',
age: 3,
eyes: 'grey'
}
];
})();
Controllers
If your data is stored in an array, you'll need to loop through it or access specific items by index number
<body ng-app="myApp">
<section ng-controller="MainController as mainCtrl">
<article ng-repeat="cat in mainCtrl.cats">
<p>My cat's name is {{cat.name}}</p>
<p>She has {{cat.eyes}} eyes and she's
{{cat.age}} years old.</p>
</article>
</section>
</body>
Exercise — Part 3
- In recipe-app/app.js, change your recipe object to an array of multiple objects and update the var name from 'recipe' to 'recipes'
- In recipe-app/index.html, use ng-repeat to loop through your recipes array and display each one on the page
Controllers
Functions can also be stored as properties
//app.js
angular
.module('todoApp', [])
.controller('TodoListController', function() {
var todoList = this;
todoList.todos = [
{text:'learn angular', done:true},
{text:'build an angular app', done:false}
];
todoList.logArg = function(arg) {
console.log(arg);
};
});
Controllers
And they can be called by events!
<!-- index.html -->
<body ng-app="todoApp">
<section ng-controller="TodoListController as todoListCtrl">
<button ng-click="todoListCtrl.logArg('hi!')">
Log me!
</button>
</section>
</body>
Exercise
- Let's look at the todo-list/todo.js & todo-list/todo-list.html
- What are the functions in todo.js doing?
- Which new directive in todo-list.html haven't we seen yet?
Dependency Injection
- Dependencies are standalone modules that can be pulled into your project for different uses
- They can be included as external files in script tags, or if you're using grunt/gulp, usually they can be included as node modules
-
Angular Local Storage is a popular module that uses the browser's local storage to persist your data without saving it to a database
Dependency Injection
angular.module('todoApp', ['LocalStorageModule'])
.controller('TodoListController', function(localStorageService) {
var todoList = this;
// todoList.todos = [
// {text:'learn angular', done:true},
// {text:'build an angular app', done:false}];
var todosInStore = localStorageService.get('myTodos');
todoList.todos = todosInStore || [];
todoList.addTodo = function() {
todoList.todos.push({text:todoList.todoText, done:false});
localStorageService.set('myTodos', todoList.todos);
todoList.todoText = '';
};
[...]
});
Exercise
- Include a script tag in todo-list/todo-list.html to reference localstorage.js
- In todo-list/todo.js, include 'LocalStorageModule' as a dependency and localStorageService as an argument in your controller callback function
- Set a var called todosInStore with the value of localStorageService.get('myTodos')
Exercise...continued
- Comment out the array of todoList.todos, and set todoList.todos to: todosInStore || []
- Within your addTodo function, before the line that sets an empty string, add a function to set local storage with the array of todos as its updated (localStorageService.set('myTodos', todoList.todos);)
$scope
-
Angular scope is an object that refers to the application model
- In this workshop so far, we've been avoiding using $scope in favor of using this in our controllers to reference the application model
- That's mainly because the $scope object is being phased out of Angular, and using this with 'controller as' syntax is now considered best practice
$scope
- That said, at this point, we do still need to use the $scope object if we want to use some of the cool Angular features that come with it
- For example, $watch is an API that watches/listens for changes in user input, and can run callback functions when changes occur
- We can use $scope.$watch to save our checked off todo list items to local storage
$scope.$watch
angular.module('todoApp', ['LocalStorageModule'])
.controller('TodoListController', function($scope, localStorageService) {
var todoList = this;
var todosInStore = localStorageService.get('myTodos');
todoList.todos = todosInStore || [];
$scope.$watch('todoList.todos', function () {
localStorageService.set('myTodos', todoList.todos);
}, true);
todoList.addTodo = function() {
todoList.todos.push({text:todoList.todoText, done:false});
//localStorageService.set('myTodos', todoList.todos);
todoList.todoText = '';
};
[...]
});
From here onward...
There are many more things you can do with Angular!
Angular 2.0
- Sometime in 2016, Angular 2.0 will be released
- It will be a rewrite largely based on ES6
- The global $scope object & jqLite will be removed
- The implementation of directives and controllers will change
- But don't worry! The fundamentals you've learned in this workshop will live on!
- Preparing for the Future of AngularJS
Next Steps
- Build Something!
- FAQ list, gallery, quiz, calculator, or whatever else you can cook up!
HTML/CSS ~ Girl Develop It