Intro to AngularJS



Intro to AngularJS

28 6


gdi-featured-angular

Slides & demo files for GDI Intro to Angular class

On Github girldevelopit / gdi-featured-angular

Show navigation

Intro to AngularJS

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!

Questions?

?
HTML/CSS ~ Girl Develop It