Skip to main content

Angular



@Component({
  selector: 'my-app',
  template: '<h1>Ultra Racing</h1>'
}) 


@ComponentUsed to apply our component decorator to our class.Decorators are a TypeScript feature.
  selector :The CSS selector for the HTML element where we want the component to
 load. The content we want to load inside our selector. 
  template






BrowserModule: Module needed for running Angular websites.

platformBrowserDynamic : Angular library that will render the website.
USING INTERPOLATION TO PRINT PROPERTIES

@Component({
 selector: 'my-app'
 template:'

{{title}}

' //interploation 
})

import {NgModule,Component} from '@angular/core'
import {BrowserModule} from '@angular/platform-broswer'
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';






ngOnInit() {
  this.carParts = CARPARTS;
} 


1.5 Our First Component

index.html


<html>
  <head>
    <title>Racing App</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">

    
     
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>

    <script src="https://unpkg.com/zone.js@0.6.25?main=browser"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.8"></script>
    <script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>

    
    <script src="systemjs.config.js"></script>

    <script>
      System.import('app/main').catch(function(err){ console.error(err);  });
    </script>
  </head>

  
  <body>
    <racing-app> <h1>Loading...</h1></racing-app>
  </body>
</html>

app/main.ts

import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

@Component({
  selector:'racing-app',
  template:`

{{heading}}

`
}) class AppComponent { heading = "Ultra Racing Schedule" } @NgModule({ imports: [ BrowserModule ], declarations: [AppComponent], bootstrap:[AppComponent] }) class AppModule {} platformBrowserDynamic() .bootstrapModule(AppModule);

______________________________________________________________________________

1.6 Making It Dynamic

app/main.ts

import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

@Component({
  selector: 'racing-app',
  template: `
    

{{ heading }}

{{race.name}}

{{race.date}} {{race.about}} ` }) class AppComponent { heading = "Ultra Racing Schedule" race = { "id": 1, "name": "Daytona Thunderdome", "date": new Date('2512-01-04T14:00:00'), "about": "Race through the ruins of an ancient Florida battle arena.", "entryFee": 3200 } } @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) class AppModule {} platformBrowserDynamic() .bootstrapModule(AppModule);


______________________________________________________________________________

2.4 Looping


______________________________________________________________________________

2.5 Conditionals 


______________________________________________________________________________

2.9 Methods 

At the bottom of our template we've added a place to display our total cost. Our total cost will be calculated by summing up the entryFee properties of ONLY the races we are racing in ( isRacing istrue). Write a method named totalCost() in our AppComponent that returns this value.


app/main.ts


import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Component } from '@angular/core';

@Component({
  selector: 'racing-app',
  template: `
  

{{heading}}

  • {{race.name}} {{race.entryFee | currency:'USD':true}}

    {{race.date | date:'MMM d, y, h:MM a'}} {{race.about}}

    Already Racing


    Total cost: {{totalCost() | currency:'USD':true}}

    ` }) export class AppComponent { heading = "Ultra Racing Schedule" cash = 10000; races = [{ "id": 1, "name": "Daytona Thunderdome", "date": new Date('2512-01-04T14:00:00'), "about": "Race through the ruins of an ancient Florida battle arena.", "entryFee": 3200, "isRacing": false }, { "id": 2, "name": "San Francisco Ruins", "date": new Date('2512-07-03T20:00:00'), "about": "Drift down the streets of a city almost sunk under the ocean.", "entryFee": 4700, "isRacing": true }, { "id": 3, "name": "New York City Skyline", "date": new Date('2512-07-12T21:00:00'), "about": "Fly between buildings in the electronic sky.", "entryFee": 4300, "isRacing": true }]; totalCost() { let sum = 0; for (let race of this.races){ if(race.isRacing) { sum += race.entryFee; } } return sum; } } @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) class AppModule {} platformBrowserDynamic().bootstrapModule(AppModule);
    ______________________________________________________________________________


    3.3 Refactoring Classes

    Both our app.component.ts and our races.component.ts are missing the export keyword to allow their classes to be imported. Could you add them where they’re needed?

    app/app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'racing-app',
      template: `
        

    {{heading}}

    my-races ` }) export class AppComponent { heading = "Ultra Racing Schedule" }

    app/races.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-races',
      template: `
        

    Cash left to enter races: {{cashLeft() | currency:'USD':true}}

    • {{race.name}} {{race.entryFee | currency:'USD':true}}

      {{race.date | date:'MMM d, y, h:MM a'}} {{race.about}}

      Already Racing


      Total cost: {{totalCost() | currency:'USD':true}}

      ` }) export class RacesComponent { heading = "Ultra Racing Schedule" cash = 10000; races = [{ "id": 1, "name": "Daytona Thunderdome", "date": new Date('2512-01-04T14:00:00'), "about": "Race through the ruins of an ancient Florida battle arena.", "entryFee": 3200, "isRacing": false }, { "id": 2, "name": "San Francisco Ruins", "date": new Date('2512-07-03T20:00:00'), "about": "Drift down the streets of a city almost sunk under the ocean.", "entryFee": 4700, "isRacing": true }, { "id": 3, "name": "New York City Skyline", "date": new Date('2512-07-12T21:00:00'), "about": "Fly between buildings in the electronic sky.", "entryFee": 4300, "isRacing": true }]; totalCost() { let sum = 0; for (let race of this.races) { if (race.isRacing) sum += race.entryFee; } return sum; } cashLeft() { return this.cash - this.totalCost(); } }

      app/main.ts

      import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
      import { BrowserModule } from '@angular/platform-browser';
      import { NgModule } from '@angular/core';
      import { AppComponent } from './app.component';
      import { RacesComponent } from './races.component';
      
      @NgModule({
        imports: [ BrowserModule ],
        declarations: [ AppComponent,RacesComponent ],
        bootstrap: [ AppComponent ]
      })
      class AppModule {}
      
      platformBrowserDynamic().bootstrapModule(AppModule);

      ______________________________________________________________________________


      3.5 Adding HTML and CSS 

      app/races.component.ts

      import { Component } from '@angular/core';
      
      @Component({
        selector: 'my-races',
        templateUrl:'app/races.component.html',
        styleUrls['app/races.component.css'];
      })
      export class RacesComponent {
        heading = "Ultra Racing Schedule"
        cash = 10000;
        races = [{
          "id": 1,
          "name": "Daytona Thunderdome",
          "date": new Date('2512-01-04T14:00:00'),
          "about": "Race through the ruins of an ancient Florida battle arena.",
          "entryFee": 3200,
          "isRacing": false
        }, {
          "id": 2,
          "name": "San Francisco Ruins",
          "date": new Date('2512-07-03T20:00:00'),
          "about": "Drift down the streets of a city almost sunk under the ocean.",
          "entryFee": 4700,
          "isRacing": true
        }, {
          "id": 3,
          "name": "New York City Skyline",
          "date": new Date('2512-07-12T21:00:00'),
          "about": "Fly between buildings in the electronic sky.",
          "entryFee": 4300,
          "isRacing": true
        }];
      
        totalCost() {
          let sum = 0;
          for (let race of this.races) {
            if (race.isRacing) sum += race.entryFee;
          }
          return sum;
        }
      
        cashLeft() {
          return this.cash - this.totalCost();
        }
      
      }




      ______________________________________________________________________________

      DATA ORGANIZATION

      3.8 Modeling and Mocking 


      app/race.ts

      export class Race {
        id: number;
        name: string;
        date:  Date;
        about: string;
        entryFee: number;
        isRacing: boolean;
      }
      

      app/mocks.ts

      import { Race } from './race';
      
      export const RACES: races[]=[{
        "id": 1,
        "name": "Daytona Thunderdome",
        "date": new Date('2512-01-04T14:00:00'),
        "about": "Race through the ruins of an ancient Florida battle arena.",
        "entryFee": 3200,
        "isRacing": false
      }, {
        "id": 2,
        "name": "San Francisco Ruins",
        "date": new Date('2512-07-03T20:00:00'),
        "about": "Drift down the streets of a city almost sunk under the ocean.",
        "entryFee": 4700,
        "isRacing": true
      }, {
        "id": 3,
        "name": "New York City Skyline",
        "date": new Date('2512-07-12T21:00:00'),
        "about": "Fly between buildings in the electronic sky.",
        "entryFee": 4300,
        "isRacing": true
      }];
      

      app/races.component.ts

      import { Component } from '@angular/core';
      import { Race } from './race';
      import { RACES } from './mocks';
      
      @Component({
        selector: 'my-races',
        templateUrl: 'app/races.component.html',
        styleUrls:['app/races.component.css']
      })
      export class RacesComponent {
        heading = "Ultra Racing Schedule"
        cash = 10000;
        races: Race[];
        ngOnInit(){
          this.races = RACES;
        }
      
        totalCost() {
          let sum = 0;
          for (let race of this.races) {
            if (race.isRacing) sum += race.entryFee;
          }
          return sum;
        }
      
        cashLeft() {
          return this.cash - this.totalCost();
        }
      
      }







      ______________________________________________________________________________

      DATA  BINDING BOOST

      4.1 Property & Class Binding

      We've gone ahead and applied new HTML and CSS to our app to make it prettier. We also have two new fields in our model and mocks: image and imageDescription.

      app/races.component.html

      <main class="container" role="main">
      <h2>Cash left to enter races: <span>{{cashLeft() | currency:'USD':true}}</span> </h2>
      <ul>
        <li class="card" *ngFor="let race of races"  [class.racing]="race.isRacing" >
          <div class="panel-body">
            <div class="photo">
              <img  [alt]="race.imageDescription"  [src]= "race.image" >
            </div>
            <table class="race-info">
              <tr>
                <td>
                  <h3>{{race.name}}</h3>
                  <p class="date">{{race.date | date:'MMM d, y, h:MM a'}}</p>
                  <p class="description">{{race.about}}</p>
                </td>
                <td>
                  <p class="price">{{race.entryFee | currency:'USD':true}}</p>
                </td>
                <td>
                  <button class="button" *ngIf="!race.isRacing">Enter Race</button>
                  <div *ngIf="race.isRacing">
                    <p class="status">Racing</p>
                    <button class="button-cancel">Cancel Race</button>
                  </div>
                </td>
              </tr>
            </table>
          </div>
        </li>
      </ul>
      <div class="price-total">
        <h3>Total cost:</h3>
        <p>{{totalCost() | currency:'USD':true}}</p>
      </div>
      </main>




      ______________________________________________________________________________


      Time to implement the "Enter Race" button and "Cancel Race" link.


      app/races.component.html

      <main class="container" role="main">
      <h2>Cash left to enter races: <span>{{cashLeft() | currency:'USD':true}}</span> </h2>
      <ul>
        <li class="card" *ngFor="let race of races" [class.racing]="race.isRacing" >
          <div class="panel-body">
            <div class="photo">
              <img [src]="race.image" [alt]="race.imageDescription">
            </div>
            <table class="race-info">
              <tr>
                <td>
                  <h3>{{race.name}}</h3>
                  <p class="date">{{race.date | date:'MMM d, y, h:MM a'}}</p>
                  <p class="description">{{race.about}}</p>
                </td>
                <td>
                  <p class="price">{{race.entryFee | currency:'USD':true}}</p>
                </td>
                <td>
                  <button class="button" *ngIf="!race.isRacing" (click)="enterRace(race)"  >Enter Race</button>
                  <div *ngIf="race.isRacing">
                    <p class="status">Racing</p>
                    <button class="button-cancel" (click)="cancelRace(race)"  >Cancel Race</button>
                  </div>
                </td>
              </tr>
            </table>
          </div>
        </li>
      </ul>
      <div class="price-total">
        <h3>Total cost:</h3>
        <p>{{totalCost() | currency:'USD':true}}</p>
      </div>
      </main>
      

      app/races.component.ts

      import { Component } from '@angular/core';
      import { Race } from './race';
      import { RACES } from './mocks';
      
      @Component({
        selector: 'my-races',
        templateUrl: 'app/races.component.html',
        styleUrls:['app/races.component.css']
      })
      export class RacesComponent {
        heading = "Ultra Racing Schedule"
        cash = 10000;
        races: Race[];
      
        ngOnInit() {
          this.races = RACES;
        }
      
        totalCost() {
          let sum = 0;
          for (let race of this.races) {
            if (race.isRacing) sum += race.entryFee;
          }
          return sum;
        }
      
        cashLeft() {
          return this.cash - this.totalCost();
        }
        cancelRace(race){
         race.isRacing = false;
        }
      enterRace(race){
        if(this.cashLeft()>race.entryFee){   
          race.isRacing = true;
        }else{
             race.isRacing = false;
          alert( "You don't have enough cash");
        }  
      }
      
      
      }


      ______________________________________________________________________________


      Sending Event Data





      4.8 Input Binding

      app/races.component.html

      <main class="container" role="main">
      <h2>Money for racing: <input type="text" class="cash" [(ngModel)]="cash"></h2>
      <h2>Cash left to enter races: <span>{{cashLeft() | currency:'USD':true}}</span> </h2>
      <ul>
        <li class="card" *ngFor="let race of races" [class.racing]="race.isRacing" >
          <div class="panel-body">
            <div class="photo">
              <img [src]="race.image" [alt]="race.imageDescription">
            </div>
            <table class="race-info">
              <tr>
                <td>
                  <h3>{{race.name}}</h3>
                  <p class="date">{{race.date | date:'MMM d, y, h:MM a'}}</p>
                  <p class="description">{{race.about}}</p>
                </td>
                <td>
                  <p class="price">{{race.entryFee | currency:'USD':true}}</p>
                </td>
                <td>
                  <button class="button" *ngIf="!race.isRacing" (click)="enterRace(race)">Enter Race</button>
                  <div *ngIf="race.isRacing">
                    <p class="status">Racing</p>
                    <button class="button-cancel" (click)="cancelRace(race)">Cancel Race</button>
                  </div>
                </td>
              </tr>
            </table>
          </div>
        </li>
      </ul>
      <div class="price-total">
        <h3>Total cost:</h3>
        <p>{{totalCost() | currency:'USD':true}}</p>
      </div>
      </main>

      This symbol [()] is sometimes called?

      banana in a box

      ______________________________________________________________________________






      5.3 Moving to a Service 175 PTS


      It's time to move our mocks into services for our racing schedule app. We've gone ahead and started creating a race.service.ts file for you. Please note that this is a RaceServiceclass, not RacingDataService class like in the slides. We need your help hooking it all up.
      • app/race.service.ts

        import { RACES } from './mocks';
        import { Injectable } from '@angular/core';
        
        @Injectable()
        export class RaceService {
          getRaces() {
            return RACES;
          }
        }
        
      • app/main.ts

        import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
        import { BrowserModule } from '@angular/platform-browser';
        import { NgModule } from '@angular/core';
        import { FormsModule } from '@angular/forms';
        import { AppComponent } from './app.component';
        import { RacesComponent } from './races.component';
        import { RaceService } from './race.service';
        
        @NgModule({
          imports: [ BrowserModule, FormsModule ],
          declarations: [ AppComponent ],
          providers: [ RaceService ],
          bootstrap: [ AppComponent ]
        })
        class AppModule {}
        
        platformBrowserDynamic().bootstrapModule(AppModule);
        
      • app/races.component.ts

        import { Component } from '@angular/core';
        import { Race } from './race';
        import { RaceService } from './race.service';
        
        @Component({
          selector: 'my-races',
          templateUrl: 'app/races.component.html',
          styleUrls:['app/races.component.css']
        })
        export class RacesComponent {
          heading = "Ultra Racing Schedule"
          cash = 10000;
          races: Race[];
        
          constructor(private raceService: RaceService) { }
        
          ngOnInit() {
            this.races = this.raceService.getRaces();
          }
        
          totalCost() {
            let sum = 0;
            for (let race of this.races) {
              if (race.isRacing) sum += race.entryFee;
            }
            return sum;
          }
        
          cashLeft() {
            return this.cash - this.totalCost();
          }
        
          enterRace(race) {
            if (this.cashLeft() > race.entryFee) {
              race.isRacing = true;
            } else {
              alert("You don't have enough cash");
            }
          }
        
          cancelRace(race) {
            race.isRacing = false;
          }
        
        }


      ______________________________________________________________________________






      5.5 Over the Internet 250 PTS


      We've gone ahead and created a races.json file for you — check it out. Let's import and usehttp to fetch our data.

      ______________________________________________________________________________




      ______________________________________________________________________________













      ______________________________________________________________________________


      Exercise 1: MODULE


      app.js

      var app = angular.module('gemStore',[]);
      

      index.html

      
      <html ng-app ='gemStore'>
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body>
          <h1>{{"Hello, Angular!"}}</h1>
        </body>
      </html>


      Exercise 3: CONTROLLERS


      app.js

      (function(){
        var gem = { name: 'Azurite', price: 2.95 };
        var app = angular.module('gemStore', []);
        app.controller('StoreController',function(){
          this.product = gem;
          
        });
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body ng-controller="StoreController as store">
          <div class="product row">
            <h3>
              {{store.product.name}}
              <em class="pull-right"> {{store.product.price}}</em>
            </h3>
          </div>
        </body>
      </html>


      Exercise 4: NG-SHOW/NG-HIDE: 
      NOTICE: The value is in quotes

      Index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body class="container" ng-controller="StoreController as store">
          <div class="product row" ng-hide = "store.product.soldOut">
            <h3>
              {{store.product.name}}
              <em class="pull-right">${{store.product.price}}</em>
            </h3>
            <button ng-show = "store.product.canPurchase">Add to Cart</button>
          </div>
        </body>
      </html>


      Exercise 5: NG -REPEAT

      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('StoreController', function(){
          this.products = gems;
        });
      
        var gems = [
          { name: 'Azurite', price: 2.95 },
          { name: 'Bloodstone', price: 5.95 },
          { name: 'Zircon', price: 3.95 }
        ];
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body class="container" ng-controller="StoreController as store">
          <div class="product row" ng-repeat = "product in store.products">
            <h3>
              {{product.name}}
              <em class="pull-right">${{product.price}}</em>
            </h3>
          </div>
        </body>
      </html>


      Exercise 6: FILTERS


      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body class="container" ng-controller="StoreController as store">
          <div class="product row" ng-repeat="product in store.products">
            <h3>
              {{product.name}}
              <em class="pull-right">{{product.price | currency }}</em>
            </h3>
          </div>
        </body>
      </html>


      Exercise 7: FILTERS


      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body ng-controller="StoreController as store">
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>
                {{product.name}}
                <em class="pull-right">{{product.price | currency}}</em>
              </h3>
              
              <div class="gallery">
                <img ng-src = "{{product.images[0]}}" />
              </div>
            </div>
          </div>
        </body>
      </html>


      Exercise 8: DISPLAYING THE FIRST IMAGE
      ng-src

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body class="list-group" ng-controller="StoreController as store">
          
          <div class="list-group-item" ng-repeat="product in store.products">
            <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
            
            <div class="gallery">
              <div class="img-wrap">
                <img ng-src="{{product.images[0]}}" />
              </div>
              <ul class="img-thumbnails clearfix">
                <li class="small-image pull-left thumbnail" ng-repeat ="image in product.images">
                  <img ng-src="{{image}}" />
                </li>
              </ul>
            </div>
          </div>
        </body>
      </html>

      Exercise 9 : CREATING AND DISPLAYING  TAB CONTROLLER


      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('StoreController', function(){
          this.products = gems;
        });
      
       app.controller('TabController', function(){
         this.tab = 1;
         this.setTab = function(ntab){
              this.tab = ntab;
         };
           this.isSet = function(ntab){
              return this.tab == ntab;
         };
        });
      
      
        var gems = [
            {
              name: 'Azurite',
              description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
              shine: 8,
              price: 110.50,
              rarity: 7,
              color: '#CCC',
              faces: 14,
              images: [
                "images/gem-02.gif",
                "images/gem-05.gif",
                "images/gem-09.gif"
              ],
              reviews: [{
                stars: 5,
                body: "I love this gem!",
                author: "joe@example.org",
                createdOn: 1397490980837
              }, {
                stars: 1,
                body: "This gem sucks.",
                author: "tim@example.org",
                createdOn: 1397490980837
              }]
            },
            {
              name: 'Bloodstone',
              description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
              shine: 9,
              price: 22.90,
              rarity: 6,
              color: '#EEE',
              faces: 12,
              images: [
                "images/gem-01.gif",
                "images/gem-03.gif",
                "images/gem-04.gif",
              ],
              reviews: [{
                stars: 3,
                body: "I think this gem was just OK, could honestly use more shine, IMO.",
                author: "JimmyDean@example.org",
                createdOn: 1397490980837
              }, {
                stars: 4,
                body: "Any gem with 12 faces is for me!",
                author: "gemsRock@example.org",
                createdOn: 1397490980837
              }]
            },
            {
              name: 'Zircon',
              description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
              shine: 70,
              price: 1100,
              rarity: 2,
              color: '#000',
              faces: 6,
              images: [
                "images/gem-06.gif",
                "images/gem-07.gif",
                "images/gem-09.gif"
              ],
              reviews: [{
                stars: 1,
                body: "This gem is WAY too expensive for its rarity value.",
                author: "turtleguyy@example.org",
                createdOn: 1397490980837
              }, {
                stars: 1,
                body: "BBW: High Shine != High Quality.",
                author: "LouisW407@example.org",
                createdOn: 1397490980837
              }, {
                stars: 1,
                body: "Don't waste your rubles!",
                author: "nat@example.org",
                createdOn: 1397490980837
              }]
            }
          ];
      })();

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body class="list-group" ng-controller="StoreController as store">
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
          <div class="list-group-item" ng-repeat="product in store.products">
            <h3>
              {{product.name}}
              <em class="pull-right">{{product.price | currency}}</em>
            </h3>
            <section ng-show="product.images.length">
              <img ng-src="{{product.images[0]}}" />
              <ul class="list-inline thumbs">
                <li class="thumbnail" ng-repeat="image in product.images">
                  <img ng-src="{{image}}" />
                </li>
              </ul>
            </section>
      
            <section class="tab" ng-controller="TabController as ctrl">
              <ul class="nav nav-pills">
                <li ng-class = "{active:ctrl.isSet(1)}">
                  <a href ng-click = "ctrl.setTab(1)">Description</a></li>
                <li ng-class = "{active:ctrl.isSet(2)}">
                  <a href   ng-click = "ctrl.setTab(2)">Specs</a></li>
                <li ng-class = "{active:ctrl.isSet(3)}">
                  <a href   ng-click = "ctrl.setTab(3)">Reviews</a></li>
              </ul>
              <div ng-show = "ctrl.isSet(1)">
                <h4>Description</h4>
                <blockquote>{{product.description}}</blockquote>
              </div>
              <div ng-show = "ctrl.isSet(2)">
                <h4>Specs</h4>
                <blockquote>Shine:{{product.shine}} </blockquote>
              </div>
              <div  ng-show = "ctrl.isSet(3)">
                <h4>Reviews</h4>
                <blockquote></blockquote>
              </div>
            </section>
          </div>
        </body>
      </html>


      Exercise 10 : CREATE & USING GALLERY CONTROLLER

      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
       app.controller('GalleryController',function(){
          this.current = 0;
          this.setCurrent = function(value) {
               this.current = value || 0;
            };
      
        });
      
        app.controller('StoreController', function(){
          this.products = gems;
        });
      
        app.controller('TabController', function(){
          this.tab = 1;
      
          this.setTab = function(newValue){
            this.tab = newValue;
          };
      
          this.isSet = function(tabName){
            return this.tab === tabName;
          };
        });
      
        var gems = [
          {
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org",
              createdOn: 1397490980837
            }]
          },
          {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif",
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org",
              createdOn: 1397490980837
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org",
              createdOn: 1397490980837
            }]
          },
          {
            name: 'Zircon',
            description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
            shine: 70,
            price: 1100,
            rarity: 2,
            color: '#000',
            faces: 6,
            images: [
              "images/gem-06.gif",
              "images/gem-07.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 1,
              body: "This gem is WAY too expensive for its rarity value.",
              author: "turtleguyy@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "BBW: High Shine != High Quality.",
              author: "LouisW407@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "Don't waste your rubles!",
              author: "nat@example.org",
              createdOn: 1397490980837
            }]
          }
        ];
      })();


      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body class="list-group" ng-controller="StoreController as store">
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
          <div class="list-group-item" ng-repeat="product in store.products">
            <h3>
              {{product.name}}
              <em class="pull-right">{{product.price | currency}}</em>
            </h3>
      
            
            <div class='gallery' ng-show="product.images.length" ng-controller="GalleryController as gallery">
              <img ng-src="{{product.images[gallery.current]}}" />
              <ul class="list-inline thumbs">
                <li class="thumbnail" ng-repeat="image in product.images">
                  <img ng-src="{{image}}" />
                </li>
              </ul>
            </div>
      
            <section class="tab" ng-controller="TabController as tab">
              <ul class="nav nav-pills">
                <li ng-class="{ active: tab.isSet(1) }">
                  <a href ng-click="tab.setTab(1)">Description</a></li>
                <li ng-class="{ active: tab.isSet(2) }">
                  <a href ng-click="tab.setTab(2)">Specs</a></li>
                <li ng-class="{ active: tab.isSet(3) }">
                  <a href ng-click="tab.setTab(3)">Reviews</a></li>
              </ul>
              <div ng-show="tab.isSet(1)">
                <h4>Description</h4>
                <blockquote>{{product.description}}</blockquote>
              </div>
              <div ng-show="tab.isSet(2)">
                <h4>Specs</h4>
                <blockquote>Shine: {{product.shine}}</blockquote>
              </div>
              <div ng-show="tab.isSet(3)">
                <h4>Reviews</h4>
              </div>
            </section>
          </div>
        </body>
      </html>


      Exercise 10 : GALLERY CONTROLLER

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
      
              
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href="" ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href="" ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href="" ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
      
                
                <div ng-show="tab.isSet(1)">
                  <h4>Description</h4>
                  <blockquote>{{product.description}}</blockquote>
                </div>
      
                
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <blockquote>Shine: {{product.shine}}</blockquote>
                </div>
      
                
                <div ng-show="tab.isSet(3)">
      
                  
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">-{{review.author}}</cite>
                      </blockquote>
                    </li>
                  </ul>
      
                  
                  <form name="reviewForm">
                    
                    <blockquote>
                      {{review.body}}
                      <strong>{{review.stars}} Stars</strong>
                      
                      <cite class="clearfix">-{{review.author}}</cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model="review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]"  title="Stars">
                        <option value="">Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model="review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model="review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
      
                </div>
      
              </section>
            </div>
          </div>
        </body>
      </html>



      Exercise 11 : CREATE & USING REVIEW CONTROLLER


      index.html


      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body ng-controller="StoreController as store">
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
          <div class="list-group">
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href="" ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href="" ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href="" ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
                <div ng-show="tab.isSet(1)">
                  <h4>Description</h4>
                  <blockquote>{{product.description}}</blockquote>
                </div>
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <blockquote>Shine: {{product.shine}}</blockquote>
                </div>
                <div ng-show="tab.isSet(3)">
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">—{{review.author}}</cite>
                      </blockquote>
                    </li>
                  </ul>
      
                  
                  <form name="reviewForm">
                    
                    <blockquote>
                      <strong> Stars</strong>
                      
                      <cite class="clearfix"></cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model ="review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]"  title="Stars">
                        <option value="">Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model ="review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model ="review.author"  type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
      
                </div>
              </section>
            </div>
          </div>
        </body>
      </html>


      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('StoreController', function(){
          this.products = gems;
        });
      
        app.controller('TabController', function(){
          this.tab = 1;
      
          this.setTab = function(tab){
            this.tab = tab;
          };
      
          this.isSet = function(tab){
            return (this.tab === tab);
          };
        });
      
        app.controller('GalleryController', function(){
          this.current = 0;
      
          this.setCurrent = function(index){
            this.current = index;
          };
        });
      
        app.controller('ReviewController',function(){
          this.review = {};
          this.addReview = function(product){
          product.reviews.push(this.review);
          this.review = {};
          };
         
        });
      
        var gems = [
          {
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org",
              createdOn: 1397490980837
            }]
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif",
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org",
              createdOn: 1397490980837
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org",
              createdOn: 1397490980837
            }]
          }, {
            name: 'Zircon',
            description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
            shine: 70,
            price: 1100,
            rarity: 2,
            color: '#000',
            faces: 6,
            images: [
              "images/gem-06.gif",
              "images/gem-07.gif",
              "images/gem-08.gif"
            ],
            reviews: [{
              stars: 1,
              body: "This gem is WAY too expensive for its rarity value.",
              author: "turtleguyy@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "BBW: High Shine != High Quality.",
              author: "LouisW407@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "Don't waste your rubles!",
              author: "nat@example.org",
              createdOn: 1397490980837
            }]
          }
        ];
      })();


      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body ng-controller="StoreController as store">
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
          <div class="list-group">
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href="" ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href="" ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href="" ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
                <div ng-show="tab.isSet(1)">
                  <h4>Description</h4>
                  <blockquote>{{product.description}}</blockquote>
                </div>
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <blockquote>Shine: {{product.shine}}</blockquote>
                </div>
                <div ng-show="tab.isSet(3)">
                  
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">—{{review.author}}</cite>
                      </blockquote>
                    </li>
                  </ul>
      
                  
                  <form name="reviewForm" ng-controller="ReviewController as reviewCtrl"   ng-submit="reviewCtrl.addReview(product)" >
      
                    
                    <blockquote>
                      <strong>{{reviewCtrl.review.stars}} Stars</strong>
                      {{reviewCtrl.review.body}}
                      <cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
                        <option value="">Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
                </div>
              </section>
            </div>
          </div>
        </body>
      </html>


      FORM VALIDATION

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
      
              
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href="" ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href="" ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href="" ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
      
                
                <div ng-show="tab.isSet(1)">
                  <h4>Description</h4>
                  <blockquote>{{product.description}}</blockquote>
                </div>
      
                
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <blockquote>Shine: {{product.shine}}</blockquote>
                </div>
      
                
                <div ng-show="tab.isSet(3)">
                  
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">—{{review.author}}</cite>
                      </blockquote>
                    </li>
                  </ul>
      
                  
                  <form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)" novalidate>
      
                    
                    <blockquote >
                      <strong>{{reviewCtrl.review.stars}} Stars</strong>
                      {{reviewCtrl.review.body}}
                      <cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars" required>
                        <option value="">Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email"  required/>
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
                </div>
      
              </section>
            </div>
      
          </div>
        </body>
      </html>




      FORM STYLING

      application.css

      .ng-invalid.ng-dirty{
        border-color:red
      }
      .ng-valid.ng-dirty{
        border-color:green
      }




      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('StoreController', function() {
          this.products = gems;
        });
      
        app.controller("TabController", function() {
          this.tab = 1;
      
          this.isSet = function(checkTab) {
            return this.tab === checkTab;
          };
      
          this.setTab = function(setTab) {
            this.tab = setTab;
          };
        });
      
        app.controller('GalleryController', function(){
          this.current = 0;
      
          this.setCurrent = function(imageNumber){
            this.current = imageNumber || 0;
          };
        });
      
        app.controller("ReviewController", function(){
      
          this.review = {};
      
          this.addReview = function(product){
            this.review.createdOn = Date.now();
            product.reviews.push(this.review);
            this.review = {};
          };
        });
      
        var gems = [{
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org",
              createdOn: 1397490980837
            }]
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif",
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org",
              createdOn: 1397490980837
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org",
              createdOn: 1397490980837
            }]
          }, {
            name: 'Zircon',
            description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
            shine: 70,
            price: 1100,
            rarity: 2,
            color: '#000',
            faces: 6,
            images: [
              "images/gem-06.gif",
              "images/gem-07.gif",
              "images/gem-08.gif"
            ],
            reviews: [{
              stars: 1,
              body: "This gem is WAY too expensive for its rarity value.",
              author: "turtleguyy@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "BBW: High Shine != High Quality.",
              author: "LouisW407@example.org",
              createdOn: 1397490980837
            }, {
              stars: 1,
              body: "Don't waste your rubles!",
              author: "nat@example.org",
              createdOn: 1397490980837
            }]
          }];
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
      
              
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
      
                
                <div ng-show="tab.isSet(1)">
                  <h4>Description</h4>
                  <blockquote>{{product.description}}</blockquote>
                </div>
      
                
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <blockquote>Shine: {{product.shine}}</blockquote>
                </div>
      
                
                <div ng-show="tab.isSet(3)">
                  
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">—{{review.author}}+"on"+{{review.createdOn |date}}</cite>
                      </blockquote>
                    </li>
                  </ul>
      
                  
                  <form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)">
      
                    
                    <blockquote >
                      <strong>{{reviewCtrl.review.stars}} Stars</strong>
                      {{reviewCtrl.review.body}}
                      <cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
                        <option value>Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
                </div>
      
              </section>
            </div>
      
          </div>
        </body>
      </html>



      Exercise 12 : REFACTORING DESCRIPTION TAB


      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
      
              
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
      
                
           <div ng-show="tab.isSet(1)" ng-include = "'product-description.html'"></div>
      
                
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <ul class="list-unstyled">
                    <li>
                      <strong>Shine</strong>
                      : {{product.shine}}</li>
                    <li>
                      <strong>Faces</strong>
                      : {{product.faces}}</li>
                    <li>
                      <strong>Rarity</strong>
                      : {{product.rarity}}</li>
                    <li>
                      <strong>Color</strong>
                      : {{product.color}}</li>
                  </ul>
                </div>
      
                
                <div ng-show="tab.isSet(3)">
                  
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">—{{review.author}}</cite>
                      </blockquote>
                    </li>  
                  </ul>
      
                  
                  <form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)">
      
                    
                    <blockquote >
                      <strong>{{reviewCtrl.review.stars}} Stars</strong>
                      {{reviewCtrl.review.body}}
                      <cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
                        <option value>Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
                </div>
      
              </section>
            </div>
      
          </div>
        </body>
      </html>
      

      product-description.html

      
      
                  <h4>Description</h4>
                  <blockquote>{{product.description}}</blockquote>
       


      CREATING AN ELEMENT DIRECTIVE

      4.3 Creating an Element Directive


      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('GalleryController', function(){
          this.current = 0;
          this.setCurrent = function(imageNumber){
            this.current = imageNumber || 0;
          };
        });
      
        app.controller('StoreController', function() {
          this.products = gems;
        });
      
        app.controller("TabController", function() {
          this.tab = 1;
      
          this.isSet = function(checkTab) {
            return this.tab === checkTab;
          };
      
          this.setTab = function(setTab) {
            this.tab = setTab;
          };
        });
      
        app.controller("ReviewController", function(){
      
          this.review = {};
      
          this.addReview = function(product){
            product.reviews.push(this.review);
            this.review = {};
          };
      
        });
      
        app.directive("productDescription",function(){
          return {
              restrict:'E',
              templateUrl:"product-description.html"
            };
        });
      
        var gems = [
          {
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org"
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org"
            }]
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif"
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org"
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org"
            }]
            }, {
              name: 'Zircon',
              description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
              shine: 70,
              price: 1100,
              rarity: 2,
              color: '#000',
              faces: 6,
              images: [
                "images/gem-06.gif",
                "images/gem-07.gif",
                "images/gem-08.gif"
              ],
              reviews: [{
                stars: 1,
                body: "This gem is WAY too expensive for its rarity value.",
                author: "turtleguyy@example.org"
              }, {
                stars: 1,
                body: "BBW: High Shine != High Quality.",
                author: "LouisW407@example.org"
              }, {
                stars: 1,
                body: "Don't waste your rubles!",
                author: "nat@example.org"
              }]
          }
        ];
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
      
              
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
      
                
             
                <product-description ng-show="tab.isSet(1)" ></product-description>
      
                
                <div ng-show="tab.isSet(2)">
                  <h4>Specs</h4>
                  <ul class="list-unstyled">
                    <li>
                      <strong>Shine</strong>
                      : {{product.shine}}</li>
                    <li>
                      <strong>Faces</strong>
                      : {{product.faces}}</li>
                    <li>
                      <strong>Rarity</strong>
                      : {{product.rarity}}</li>
                    <li>
                      <strong>Color</strong>
                      : {{product.color}}</li>
                  </ul>
                </div>
      
                
                <div ng-show="tab.isSet(3)">
                  
                  <ul>
                    <h4>Reviews</h4>
                    <li ng-repeat="review in product.reviews">
                      <blockquote>
                        <strong>{{review.stars}} Stars</strong>
                        {{review.body}}
                        <cite class="clearfix">—{{review.author}}</cite>
                      </blockquote>
                    </li>
                  </ul>
      
                  
                  <form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)">
      
                    
                    <blockquote >
                      <strong>{{reviewCtrl.review.stars}} Stars</strong>
                      {{reviewCtrl.review.body}}
                      <cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
                    </blockquote>
      
                    
                    <h4>Submit a Review</h4>
                    <fieldset class="form-group">
                      <select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
                        <option value>Rate the Product</option>
                      </select>
                    </fieldset>
                    <fieldset class="form-group">
                      <textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
                    </fieldset>
                    <fieldset class="form-group">
                      <input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
                    </fieldset>
                    <fieldset class="form-group">
                      <input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
                    </fieldset>
                  </form>
                </div>
              </section>
            </div>
          </div>
        </body>
      </html>


      4.4 Creating an Attribute Directive 


      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
        <body ng-controller="StoreController as store">
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
          <div class="list-group">
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
              <section ng-controller="TabController as tab">
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
                <div ng-show="tab.isSet(1)" ng-include="product-description.html"></div>
      
                
                <div ng-show="tab.isSet(2)"  product-specs>
      
                </div>
      
                
                <product-reviews ng-show="tab.isSet(3)"></product-reviews>
              </section>
            </div>
          </div>
        </body>
      </html>
      

      product-specs.html

      <h4>Specs</h4>
                  <ul class="list-unstyled">
                    <li>
                      <strong>Shine</strong>
                      : {{product.shine}}</li>
                    <li>
                      <strong>Faces</strong>
                      : {{product.faces}}</li>
                    <li>
                      <strong>Rarity</strong>
                      : {{product.rarity}}</li>
                    <li>
                      <strong>Color</strong>
                      : {{product.color}}</li>
                  </ul> 
      

      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('GalleryController', function(){
          this.current = 0;
          this.setCurrent = function(imageNumber){
            this.current = imageNumber || 0;
          };
        });
      
        app.controller('StoreController', function() {
          this.products = gems;
        });
      
        app.controller("TabController", function() {
          this.tab = 1;
      
          this.isSet = function(checkTab) {
            return this.tab === checkTab;
          };
      
          this.setTab = function(setTab) {
            this.tab = setTab;
          };
        });
      
        app.controller("ReviewController", function(){
      
          this.review = {};
      
          this.addReview = function(product){
            product.reviews.push(this.review);
            this.review = {};
          };
      
        });
      
        app.directive("productDescriptions", function() {
          return {
            restrict: 'E',
            templateUrl: "product-description.html"
          };
        });
      
        app.directive("productReviews", function() {
          return {
            restrict: 'E',
            templateUrl: "product-reviews.html"
          };
        });
      
        app.directive("productSpecs",function(){
          return {
             restrict:'A',
             templateUrl:"product-specs.html"
          };
          
        });
      
        var gems = [
          {
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org"
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org"
            }]
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif"
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org"
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org"
            }]
            }, {
              name: 'Zircon',
              description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
              shine: 70,
              price: 1100,
              rarity: 2,
              color: '#000',
              faces: 6,
              images: [
                "images/gem-06.gif",
                "images/gem-07.gif",
                "images/gem-08.gif"
              ],
              reviews: [{
                stars: 1,
                body: "This gem is WAY too expensive for its rarity value.",
                author: "turtleguyy@example.org"
              }, {
                stars: 1,
                body: "BBW: High Shine != High Quality.",
                author: "LouisW407@example.org"
              }, {
                stars: 1,
                body: "Don't waste your rubles!",
                author: "nat@example.org"
              }]
          }
        ];
      })();
      _________________________________________________________________________________

      DIRECTIVE CONTROLLERS

      DC :EXERCISE 1

      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.controller('GalleryController', function(){
          this.current = 0;
          this.setCurrent = function(imageNumber){
            this.current = imageNumber || 0;
          };
        });
      
        app.controller('StoreController', function() {
          this.products = gems;
        });
      
      
          app.directive("productTabs",function(){
          return{
            restrict:'E',
            templateUrl:'product-tabs.html',
            controller: function() {
                  this.tab = 1;
                  this.isSet = function(checkTab) {
                     return this.tab === checkTab;
                   };
                  this.setTab = function(setTab) {
                      this.tab = setTab;
                   };
              },
            controllerAs:'tab'
        };
          });
      
        app.controller("ReviewController", function(){
      
          this.review = {};
      
          this.addReview = function(product){
            product.reviews.push(this.review);
            this.review = {};
          };
      
        });
      
        app.directive("productDescription", function() {
          return {
            restrict: 'E',
            templateUrl: "product-description.html"
          };
        });
      
        app.directive("productReviews", function() {
          return {
            restrict: 'E',
            templateUrl: "product-reviews.html"
          };
        });
      
        app.directive("productSpecs", function() {
          return {
            restrict:"A",
            templateUrl: "product-specs.html"
          };
        });
      
        var gems = [
          {
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org"
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org"
            }]
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif"
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org"
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org"
            }]
            }, {
              name: 'Zircon',
              description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
              shine: 70,
              price: 1100,
              rarity: 2,
              color: '#000',
              faces: 6,
              images: [
                "images/gem-06.gif",
                "images/gem-07.gif",
                "images/gem-08.gif"
              ],
              reviews: [{
                stars: 1,
                body: "This gem is WAY too expensive for its rarity value.",
                author: "turtleguyy@example.org"
              }, {
                stars: 1,
                body: "BBW: High Shine != High Quality.",
                author: "LouisW407@example.org"
              }, {
                stars: 1,
                body: "Don't waste your rubles!",
                author: "nat@example.org"
              }]
          }
        ];
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
                <div class="img-wrap">
                  <img ng-src="{{product.images[gallery.current]}}" />
                </div>
                <ul class="img-thumbnails clearfix">
                  <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                  </li>
                </ul>
              </div>
      
              
              <product-tabs></product-tabs>
            </div>
      
          </div>
        </body>
      </html>
      

      product-tabs.html

      <section >
                <ul class="nav nav-pills">
                  <li ng-class="{ active:tab.isSet(1) }">
                    <a href ng-click="tab.setTab(1)">Description</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(2) }">
                    <a href ng-click="tab.setTab(2)">Specs</a>
                  </li>
                  <li ng-class="{ active:tab.isSet(3) }">
                    <a href ng-click="tab.setTab(3)">Reviews</a>
                  </li>
                </ul>
      
                
                <div ng-show="tab.isSet(1)" ng-include="'product-description.html'">
                </div>
      
                
                <div product-specs ng-show="tab.isSet(2)"></div>
      
                
                <product-reviews ng-show="tab.isSet(3)"></product-reviews>
      
              </section> 



      _______________________________________________________________________________

      4.7 Refactoring Product Gallery



      app.js

      (function() {
        var app = angular.module('gemStore', []);
      
        app.directive('productGallery',function(){
          return{
            restrict:'E',
            templateUrl:'product-gallery.html',
            controller: function(){
                this.current = 0;
               this.setCurrent = function(imageNumber){
               this.current = imageNumber || 0;
            };
            },
            controllerAs : 'gallery'
            
          };
        });
      
        app.controller('StoreController', function() {
          this.products = gems;
        });
      
        app.controller("ReviewController", function(){
      
          this.review = {};
      
          this.addReview = function(product){
            product.reviews.push(this.review);
            this.review = {};
          };
      
        });
      
        app.directive("productDescriptions", function() {
          return {
            restrict: 'E',
            templateUrl: "product-description.html"
          };
        });
      
        app.directive("productReviews", function() {
          return {
            restrict: 'E',
            templateUrl: "product-reviews.html"
          };
        });
      
        app.directive("productSpecs", function() {
          return {
            restrict:"A",
            templateUrl: "product-specs.html"
          };
        });
      
        app.directive("productTabs", function() {
          return {
            restrict: "E",
            templateUrl: "product-tabs.html",
            controller: function() {
              this.tab = 1;
      
              this.isSet = function(checkTab) {
                return this.tab === checkTab;
              };
      
              this.setTab = function(activeTab) {
                this.tab = activeTab;
              };
            },
            controllerAs: "tab"
          };
        });
      
        var gems = [
          {
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: [{
              stars: 5,
              body: "I love this gem!",
              author: "joe@example.org"
            }, {
              stars: 1,
              body: "This gem sucks.",
              author: "tim@example.org"
            }]
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif"
            ],
            reviews: [{
              stars: 3,
              body: "I think this gem was just OK, could honestly use more shine, IMO.",
              author: "JimmyDean@example.org"
            }, {
              stars: 4,
              body: "Any gem with 12 faces is for me!",
              author: "gemsRock@example.org"
            }]
            }, {
              name: 'Zircon',
              description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
              shine: 70,
              price: 1100,
              rarity: 2,
              color: '#000',
              faces: 6,
              images: [
                "images/gem-06.gif",
                "images/gem-07.gif",
                "images/gem-08.gif"
              ],
              reviews: [{
                stars: 1,
                body: "This gem is WAY too expensive for its rarity value.",
                author: "turtleguyy@example.org"
              }, {
                stars: 1,
                body: "BBW: High Shine != High Quality.",
                author: "LouisW407@example.org"
              }, {
                stars: 1,
                body: "Don't waste your rubles!",
                author: "nat@example.org"
              }]
          }
        ];
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
                <product-gallery></product-gallery>
      
              
              <product-tabs></product-tabs>
      
            </div>
          </div>
        </body>
      </html>
      

      product-gallery.html

      <div ng-show="product.images.length">
        <div class="img-wrap">
          <img ng-src="{{product.images[gallery.current]}}" />
        </div>
        <ul class="img-thumbnails clearfix">
          <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
            <img ng-src="{{image}}" />
          </li>
        </ul>
      </div> 

      _______________________________________________________________________________


      _______________________________________________________________________________

      5.2 Refactoring into a Module


      products.js

      (function() {
        var app = angular.module("store-directives",[]);
       
        app.directive("productDescription", function() {
          return {
            restrict: 'E',
            templateUrl: "product-description.html"
          };
        });
      
        app.directive("productReviews", function() {
          return {
            restrict: 'E',
            templateUrl: "product-reviews.html"
          };
        });
      
        app.directive("productSpecs", function() {
          return {
            restrict:"A",
            templateUrl: "product-specs.html"
          };
        });
      
        app.directive("productTabs", function() {
          return {
            restrict: "E",
            templateUrl: "product-tabs.html",
            controller: function() {
              this.tab = 1;
      
              this.isSet = function(checkTab) {
                return this.tab === checkTab;
              };
      
              this.setTab = function(activeTab) {
                this.tab = activeTab;
              };
            },
            controllerAs: "tab"
          };
        });
      
        app.directive("productGallery", function() {
          return {
            restrict: "E",
            templateUrl: "product-gallery.html",
            controller: function() {
              this.current = 0;
              this.setCurrent = function(imageNumber){
                this.current = imageNumber || 0;
              };
            },
            controllerAs: "gallery"
          };
        });
        
      })();
      

      app.js

      (function() {
        var app = angular.module('gemStore', ['store-directives']);
      
        app.controller('StoreController', function(){
          this.products = gems;
        });
      
        app.controller('ReviewController', function() {
          this.review = {};
      
          this.addReview = function(product) {
            product.reviews.push(this.review);
      
            this.review = {};
          };
        });
      
        
      
        var gems = [{
            name: 'Azurite',
            description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
            shine: 8,
            price: 110.50,
            rarity: 7,
            color: '#CCC',
            faces: 14,
            images: [
              "images/gem-02.gif",
              "images/gem-05.gif",
              "images/gem-09.gif"
            ],
            reviews: []
          }, {
            name: 'Bloodstone',
            description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
            shine: 9,
            price: 22.90,
            rarity: 6,
            color: '#EEE',
            faces: 12,
            images: [
              "images/gem-01.gif",
              "images/gem-03.gif",
              "images/gem-04.gif",
            ],
            reviews: []
          }, {
            name: 'Zircon',
            description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
            shine: 70,
            price: 1100,
            rarity: 2,
            color: '#000',
            faces: 6,
            images: [
              "images/gem-06.gif",
              "images/gem-07.gif",
              "images/gem-08.gif"
            ],
            reviews: []
          }];
      })();
      

      index.html

      
      <html ng-app="gemStore">
        <head>
          <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
          <script type="text/javascript" src="angular.min.js"></script>
          <script type="text/javascript" src="app.js"></script>
           <script type="text/javascript" src="products.js"></script>
        </head>
      
        <body ng-controller="StoreController as store">
          
          <header>
            <h1 class="text-center">Flatlander Crafted Gems</h1>
            <h2 class="text-center">– an Angular store –</h2>
          </header>
      
          
          <div class="list-group">
            
            <div class="list-group-item" ng-repeat="product in store.products">
              <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
      
              
              <product-gallery></product-gallery>
      
              
              <product-tabs></product-tabs>
            </div>
      
          </div>
        </body>
      </html>

      _______________________________________________________________________________

      5.4 Built-in AngularJS Services

      app.js

      (function() {
        var app = angular.module('gemStore', ['store-directives']);
      
        app.controller('StoreController',['$http',function($http){
          var store = this;
          store.products = [];
          $http.get('/store-products.json').success(function(data){
            store.products = data;
          });
        }]);
      
        app.controller('ReviewController', function() {
          this.review = {};
      
          this.addReview = function(product) {
            product.reviews.push(this.review);
      
            this.review = {};
          };
        });
      })();

      ______________________________________________________


      1.2 The Beginning of All Routes


      js/app.js

      angular.module('NoteWrangler',['ngRoute'])
             .config(['$routeProvider',function($routeProvider){
               $routeProvider.when('/notes',{
                 templateUrl:'templates/pages/notes/index.html'
               });
               
             }]);
               
                
      

      index.html

      
      <html lang="en" ng-app="NoteWrangler">
      
        <head>
          <meta charset="utf-8">
          <title>Note Wrangler</title>
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <link rel="stylesheet" href="css/application.css" />
        </head>
      
        <body>
          <div class="nav-wrapper has-dropdown">
            <div class="nav-content">
              <div class="wrapper">
                <div class="nav-content-layout">
                  <div class="nav-list">
      
                    <a href="#/"
                    class="list-item"
                    ng-click="selected = 'notes'"
                    ng-class="{'active': selected == 'notes'}"> Notes </a>
      
                    <a href="#/users"
                    class="list-item"
                    ng-click="selected = 'users'"
                    ng-class="{'active': selected == 'users'}"> Users </a>
      
                  </div>
                </div>
              </div>
            </div>
          </div>
      
          <div class="hero-wrapper">
            <div class="hero-content">
              <div class="hero"></div>
            </div>
          </div>
      
          <div class="main-wrapper">
            <div ng-view></div>
          </div>
      
          
          <script src="./js/vendor/jquery.js"></script>
          <script src="./js/vendor/angular.js"></script>
          <script src="./js/vendor/angular-route.js"></script>
      
          <script src="./js/app.js"></script>
      
          
          <script src="./js/controllers/notes-create-controller.js"></script>
          <script src="./js/controllers/notes-edit-controller.js"></script>
          <script src="./js/controllers/notes-index-controller.js"></script>
          <script src="./js/controllers/notes-show-controller.js"></script>
          <script src="./js/controllers/users-index-controller.js"></script>
          <script src="./js/controllers/users-show-controller.js"></script>
      
      
        </body>
      </html>

      1.4 A New Route and a Root Route 


      js/app.js

      angular.module('NoteWrangler', ['ngRoute'])
      .config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/notes/new',{
          templateUrl:'templates/pages/notes/edit.html'
        }).when('/',{
          redirectTo:'/users'
        })
          .when('/notes', {
            templateUrl: 'templates/pages/notes/index.html'
          })
          .when('/users', {
            templateUrl: 'templates/pages/users/index.html'
          }).otherwise({
          redirectTo:'/notes'
        })
          ;
      
      }]);

      _________________________________________________________________________________

      llama.js

      var newLlamaRecruit = {
        llamaOne: 'Larry Llama'
      };
      
      $http({
        method:'POST',
        url:'/llamas.json',
        data: newLlamaRecruit
       });

      1.9 Inside Route Controller


      js/app.js

      angular.module('NoteWrangler', ['ngRoute'])
      .config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/', {
            redirectTo: '/users'
          })
          .when('/notes', {
            templateUrl: 'templates/pages/notes/index.html',
           controller: function($http) {
               var donkey = this; // closes over 'this'
               $http({method: 'GET', url: '/notes'}).success(function(data) {
                donkey.notes = data;
                  });
               },
        controllerAs: 'notesCtrl'
          })
          .when('/users', {
            templateUrl: 'templates/pages/users/index.html'
          })
          .when('/notes/new', {
            templateUrl: 'templates/pages/notes/edit.html'
          })
          .otherwise({
            redirectTo: '/notes'
          });
      }]);


       
         
           

      Notes


      _________________________________________________________________________________

      1.10 Outside Controller

      app/js/app.js

      angular.module('NoteWrangler', ['ngRoute'])
      .config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/', {
            redirectTo: '/users'
          })
          .when('/notes', {
            templateUrl: 'templates/pages/notes/index.html',
            controller: function($http){
              var controller = this;
              $http({method: 'GET', url: '/notes'}).success(function(data){
                controller.notes = data;
              });
            },
            controllerAs: 'notesCtrl'
          })
          .when('/users', {
            templateUrl: 'templates/pages/users/index.html'
          })
          .when('/notes/new', {
            templateUrl: 'templates/pages/notes/edit.html',
            controller :'NotesCreateController',
            controllerAs:'note'
      
          })
          .otherwise({
            redirectTo: '/notes'
          });
      }]);
      

      app/templates/pages/notes/new.html

      <div class="new-note">
        <div class="new-note-container">
          <form class="form">
            <fieldset>
              <label for="title">Title</label>
              <input name="title"  ng-model ="note.title"/>
            </fieldset>
      
            <fieldset>
              <label for="description">Description</label>
              <textarea name="description" ng-model="note.description"></textarea>
            </fieldset>
      
            <fieldset>
              <label for="content">Content</label>
              <textarea name="content" ng-model ="note.content" ></textarea>
            </fieldset>
      
            <button class="btn" ng-click= "note.saveNote(note)">Save</button>
          </form>
        </div>
      </div>
      _________________________________________________________________________________



      app/js/notes-show-controller.js

      angular.module('NoteWrangler')
      .controller('NotesShowController', ['$http','$routeParams',function($http,$routeParams) {
      var notes = this;
        $http({method:'GET',
            url: '/notes/' + $routeParams.id}).success(function(data){
             notes.note  = data;
      });
      }]);

      _________________________________________________________________________________

      2.3 Inline Controller & $scope


      js/directives/nw-card.js

      angular.module('NoteWrangler').directive('nwCard', [function() {
        return {
          restrict: 'E',
          templateUrl: 'templates/directives/nw-card.html',
          controller: function($scope) {
            $scope.header = 'Note Title';
            $scope.description = 'A lovely note description.';
          }
        };
      }]);
      

      templates/directives/nw-card.html

      <div class="card" title="{{header}}">
        <h2 class="h3">{{header}}</h2>
        <p>{{description}}</p>
      </div>

      _________________________________________________________________________________

      js/controllers/notes-index-controller.js

      angular.module('NoteWrangler')
      .controller('NotesIndexController', ['$http','$scope', function($http,$scope) {
      
      
        $http({method: 'GET', url: '/notes'}).success(function(data) {
          $scope.notes = data;
        });
      }]);
      

      js/routes.js

      angular.module('NoteWrangler', ['ngRoute'])
      .config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/', {
            redirectTo: '/users'
          })
          .when('/notes', {
            templateUrl: 'templates/pages/notes/index.html',
            controller: 'NotesIndexController',
          })
          .when('/users', {
            templateUrl: 'templates/pages/users/index.html'
          })
          .when('/notes/new', {
            templateUrl: 'templates/pages/notes/edit.html',
            controller: 'NotesCreateController'
          })
          .when('/notes/:id', {
            templateUrl: 'templates/pages/notes/show.html',
            controller: 'NotesShowController'
          })
          .otherwise({
            redirectTo: '/notes'
          });
      }]);
      

      templates/pages/notes/index.html

      <div class="note-wrapper">
        <div class="note-content">
          <div class="notes-header">
            <h1 title="Notes">Notes</h1>
          </div>
      
          <div class="note-wrapper">
            <a class="card-notes" ng-repeat="note in notes">
              <nw-card></nw-card>
            </a>
          </div>
      
        </div>
      </div>
      

      2.7 Setting on Scope



      angular.module('NoteWrangler', [])
      .directive("nwCard", function() {
        return {
          restrict: "E",
          templateUrl: "templates/directives/nw-card.html",
          controller: function($scope) {
            $scope.title = 'Space Llamas';
          }
        }
      });


      _________________________________________________________________________________

      2.8 A Flexible Card Directive

      nw-card.js

      angular.module('NoteWrangler')
      .directive('nwCard', function() {
        return {
          restrict: 'E',
          templateUrl: 'templates/directives/nw-card.html',
          scope:{
            header:"=",
            description :"="
          }
        };
      });
      

      nw-card.html

      <div class="card" title="{{header}}">
        <h2 class="h3">{{header}}</h2>
        <p>{{description}}</p>
      </div>

      _________________________________________________________________________________


      2.9 Making Isolation Work for You


      notes/index.html

      <div class="note-wrapper">
        <div class="note-content">
          <div class="notes-header">
            <h1 title="Notes">Notes</h1>
          </div>
          <div class="note-wrapper">
            <a class="card-notes" ng-repeat="note in notes" ng-href="#/notes/{{note.id}}">
              <nw-card header="note.title" description="note.description"></nw-card>
            </a>
          </div>
        </div>
      </div>
      

      users/index.html

      <div class="users-wrapper">
        <h1>Users</h1>
      
        <div class="users-wrapper">
          <a class="card-users" ng-repeat="user in users">
            <nw-card header ="user.name" description="user.bio"></nw-card>
          </a>
        </div>
      </div>

      _________________________________________________________________________________


      2.12 Style the Tweeted Note



      js/directives/nw-card.js


      angular.module('NoteWrangler')
      .directive('nwCard', function() {
        return {
          restrict: 'E',
          templateUrl: './templates/directives/nw-card.html',
          scope: {
            header: '=',
            description: '=',
            tweeted: '='
          },
          link: function(scope,element){
                if(scope.tweeted) {
                   element.addClass('tweeted');
                }
            
          }
          
        };
      });

      SS


      3.2 A Factory Recipe I 250 PTS

      js/services/note.js


      angular.module('NoteWrangler').factory("Note",[function NoteFactory() {
                                  
       }])
      
      ;


      3.3 A Factory Recipe II 



      js/services/note.js

      angular.module('NoteWrangler')
      .factory('Note', ['$http',function NoteFactory($http) {
      return  {
          all:function(){
            return   $http({method: 'GET', 
                    url: '/notes'});
         }
         };
      }]);
      

      js/controllers/notes-index-controller.js

      angular.module('NoteWrangler')
      .controller('NotesIndexController', ['$scope', 'Note', function($scope, Note) {
        Note.all().success(function(data){
          $scope.notes = data;
        });
      }]);


      3.5 A Tweetable Service








      3.8 Configurable Bits Need a Provider


      js/services/tweetable.js

      angular.module('NoteWrangler')
      .provider('Tweetable', function TweetableProvider() {
        var characterLength = 144;
      
        this.setLength = function(maxLength) {
          characterLength = maxLength;
        };
      
        this.$get = function($http) {
          return function(potentialTweet) {
            return $http({
              method: 'POST',
              url: 'http://gentle-spire-1153.herokuapp.com/tweet',
              data: {
                description: potentialTweet,
                maxLength: characterLength
              }
            });
          };
        };
      });



      3.9 Configuring the Tweet Length


      js/app.js

      angular.module('NoteWrangler', ['ngRoute'])
        .config(function(TweetableProvider){
        TweetableProvider.setLength(40);
        
      })
      ;
      
      



      3.11 $resource Refactor



      js/services/note.js

      angular.module('NoteWrangler')
      .factory('Note', ['$resource', function NoteFactory($resource) {
        return $resource("/notes",{},{});
      
      }]);
      

      js/app.js

      angular.module('NoteWrangler', ['ngRoute','ngResource'])
      .config(function(TweetableProvider) {
        TweetableProvider.setLength(144);
      });
      

      index.html

      
      <html lang="en" ng-app="NoteWrangler">
      
        <head>
          <meta charset="utf-8">
          <title>Note Wrangler</title>
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <link rel="stylesheet" href="css/application.css" />
        </head>
      
        <body>
          <div class="nav-wrapper has-dropdown">
            <div class="nav-content">
              <div class="wrapper">
                <div class="nav-content-layout">
                  <div class="nav-list">
                    <a href="#/notes"
                    class="list-item"
                    ng-click="selected = 'notes'"
                    ng-class="{'active': selected == 'notes'}"> Notes </a>
      
                    <a href="#/users"
                    class="list-item"
                    ng-click="selected = 'users'"
                    ng-class="{'active': selected == 'users'}"> Users </a>
                  </div>
                </div>
              </div>
            </div>
          </div>
      
          <div class="hero-wrapper">
            <div class="hero-content">
              <div class="hero"></div>
            </div>
          </div>
      
          <div class="main-wrapper">
            <div ng-view></div>
          </div>
      
          
          <script src="./js/vendor/jquery.js"></script>
          <script src="./js/vendor/angular.js"></script>
          <script src="./js/vendor/angular-route.js"></script>
           <script src="./js/vendor/angular-resource.js"></script>
      
          
          <script src="./js/app.js"></script>
          <script src="./js/routes.js"></script>
      
          
          <script src="./js/controllers/notes-create-controller.js"></script>
          <script src="./js/controllers/notes-edit-controller.js"></script>
          <script src="./js/controllers/notes-index-controller.js"></script>
          <script src="./js/controllers/notes-show-controller.js"></script>
          <script src="./js/controllers/users-index-controller.js"></script>
          <script src="./js/controllers/users-show-controller.js"></script>
      
          
          <script src="./js/directives/nw-card.js"></script>
      
          
          <script src="./js/services/note.js"></script>
          <script src="./js/services/tweetable.js"></script>
      
        </body>
      </html>

      ______________________________________________________


      3.12 Using a $resource-ful Note Service



      Instead of calling the all() method of Note, we want to assign $scope.notes the value returned from the query() method of Note.
      $scope.notes = Note.query();
      • js/controllers/notes-index-controller.js

        angular.module('NoteWrangler')
        .controller('NotesIndexController', ['$scope', 'Note', 'Tweetable', function($scope, Note, Tweetable) {
          $scope.notes = Note.query();
        
          $scope.tweetThatNote = function(noteToTweet) {
            Tweetable(noteToTweet).success(function(status) {
              console.log(status);
            });
          };
        }]);

      ______________________________________________________


      3.13 A Custom Method for Our Note $resource 













      Comments

      Popular posts from this blog

      Microservices Design patterns

      What are microservices? Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of services that are Highly maintainable and testable Loosely coupled Independently deployable Organized around business capabilities Owned by a small team The microservice architecture enables the rapid, frequent and reliable delivery of large, complex applications. It also enables an organization to evolve its technology stack. You are developing a server-side enterprise application. It must support a variety of different clients including desktop browsers, mobile browsers and native mobile applications. The application might also expose an API for 3rd parties to consume. It might also integrate with other applications via either web services or a message broker. The application handles requests (HTTP requests and messages) by executing business logic; accessing a database; exchanging messages with other systems; and returni...

      GraphQL

      What is GraphQL  API Standard invented & open-sourced by Facebook Alternative to  REST API  enables declarative data fetching  exposes single endpoint & responds to queries How it works?  Why Graphql? Improvises performance by reducing the data that is to be transferred over the internet Variety of different frontend frameworks and platforms on client-side Fast development speed & expectation for rapid feature development Why Graphql is better than REST? Flexibility & efficient  No more over /under fetching of data Over fetching : Under fetching: Insightful analytics  Schema serves as contract between client and server CORE CONCEPTS : SDL :SCHEMA DEFINITION LANGUAGE Writing Data with mutations 3 kinds of mutations creating new data updating existing data deleting existing data

      Jackson

      <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> jackson-core </artifactId> <version>2.9.6</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> jackson-annotations </artifactId> <version>2.9.6</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> jackson-databind </artifactId> <version>2.9.6</version> </dependency> CBOR encoded data with Jackson <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-cbor</artifactId> <version>2.9.6</version> </dependency> In order to read and write MessagePack encoded data <dependency> <groupId>org.msgpack</groupId> <artifactId>jackson-dataformat-msgp...