Shaping Up With AngularJS – Codeschool

app.angular(“sample” []); Note : Without [] refer to previous existing module and with [] indicate it creating new module.

Tab:

Adding new Controller

<!DOCTYPE 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>

      <!-- Image Gallery  -->
      <div class='gallery' ng-controller="GalleryController as gallery" ng-show="product.images.length">
        <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>

app.js

app.controller('ReviewController', function() {
    this.review = {};

    this.addReview = function(product) {
      product.reviews.push(this.review);

      this.review = {};
    };
  });
(function() {
  var app = angular.module('gemStore', []);

  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;
    };
  });

  app.controller('GalleryController', function(){
    this.current = 0;
    this.setCurrent = function(newGallery){
      this.current = newGallery || 0;
    };
  });

  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
      }]
    }
  ];
})();

 

Example 2:

Adding Review to the form

 <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>

Displaying the reviews for all product


  <body ng-controller="StoreController as store">
    <div class="list-group">
      <div class="list-group-item" ng-repeat="product in store.products">
        <section ng-controller="TabController as tab">
            <!--  Product Reviews List -->
          
            <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>
          </div>
        </section>

 

CREATING CUSTOM DIRECTIVE ELEMENT
===================================

index.html
 <product-description ng-show="tab.isSet(1)"></product-description>


product-description.html
-----------------------
<div>
  <h4>Description</h4>
  <blockquote>{{product.description}}</blockquote>
</div>



app.js
  app.directive("productDescription", function(){
    return{
      restrict: 'E',
      templateUrl: 'product-description.html'
    };
  });

 

CREATING CUSTOM DIRECTIVE ATTRIBUTE
====================================

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

app.directive("productSpecs", function(){
    return{
      restrict: 'A',
      templateUrl: 'product-specs.html'
    };
  });


index.html

 <div product-specs ng-show="tab.isSet(2)"></div>

 

Creating custom directive with controller
———————————————–

app.js

 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"
    };  
  });


product-task.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>

    <!--  Description Tab's Content  -->
    <div ng-show="tab.isSet(1)" ng-include="'product-description.html'"></div>

     <!--  Spec Tab's Content  -->
     <div product-specs ng-show="tmotsangSnowlion81tab.isSet(2)"></div>

      <!--  Review Tab's Content  -->
      <product-reviews ng-show="tab.isSet(3)"></product-reviews>
  </section>


index.html

<product-tabs></product-tabs>

 

Create an element directive called productGallery with controller
—————————————————————————–

app.js
  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'
    };
  });



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> 

index.html

        <product-gallery></product-gallery>

 

Creating new Module and adding dependency
—————————————————-


We have to follow three step

1. Define a modul, save as products.app

(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"
    };
  });
})();

2. Add the dependency of store-directives in app.js file

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: []
    }];
})();


Step 3: Define link of module in index.html

  <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>

 

CREATING HTTP SERVICE
———————————–

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 = {};
    };
  });
})();

AngularFireAuth

Accessing user login

import { Component, Input } from '@angular/core';
import { App, NavController, NavParams } from 'ionic-angular';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
import { TabsPage } from '../../tabs/tabs';
import { LoginPage } from '../../login/login';
import { RegisterPage } from '../../register/register';
import { EditPage } from '../edit/edit';
import { ReviewsPage } from '../reviews/reviews';
import { AdditionalDetailsPage } from '../additional-details/additional-details';
import { auditTrail } from 'angularfire2/database';
import { ProfileRef } from '../../../models/profile';
import { PhotoIdentity } from '../../../models/photoIdentity';
import { ProfilePhoto } from '../../../models/profilePhoto';
import {} from '../pages/register/reigister';
import * as firebase from 'firebase';

@Component({
  selector: 'page-view',
  templateUrl: 'view.html',
})

export class ViewPage {

  displayName;
  id: string;
  userCheck: boolean;
  email;
  photoURL;
  profileRef = {} as ProfileRef;
  selectedFile: File;
  photoIdentity = {} as PhotoIdentity;
  profilePhoto = {} as ProfilePhoto;

  // private baseProfilePath: string = '/profileImages';
  private basePath: string = '/photoIdentities';

  constructor(public auth: AngularFireAuth, public navCtrl: NavController, public navParams: NavParams, private app: App, private db: AngularFireDatabase) {
    

    if (auth.auth.currentUser !== null) {
      this.userCheck = true;
      this.id = auth.auth.currentUser.uid;
      this.displayName = auth.auth.currentUser.displayName;
      this.email = auth.auth.currentUser.email;
      this.photoURL = auth.auth.currentUser.photoURL || 'assets/images/no-photo.jpg';
    }else{
      this.userCheck =false;
    }
    console.log("userCheck", this.userCheck);
  }

  ionViewDidLoad() {
    if (this.auth.auth.currentUser !== null) {
      this.db.object('/profiles/' + this.auth.auth.currentUser.uid).valueChanges().subscribe(data => {
        this.profileRef = <ProfileRef>data;

      },
      err => console.log("error in retrieving user from profile : " + err),
        () => console.log("user profile key retrieve successful"));
    }
  }

  login() {
    this.app.getRootNav().setRoot(LoginPage);
  }

  register() {
    this.app.getRootNav().setRoot(RegisterPage);
  }

  logout() {
    this.auth.auth.signOut();
    this.app.getRootNav().setRoot(TabsPage);
  }

  editProfile(id) {
    this.navCtrl.push(EditPage, { userId: id });
  }

  addAdditionalInfo(id) {
    this.navCtrl.push(AdditionalDetailsPage, { userId: id });
  }

  //Edit Profile Picture
  detectProfileFile(event) {
    this.selectedFile = event.target.files[0];
    let file = this.selectedFile;
    this.profilePhoto = new ProfilePhoto(file);

    let storageRef = firebase.storage().ref();

    let profilePhotoTask = storageRef.child(`/profileImages/${this.id}`).put(this.profilePhoto.file);

    profilePhotoTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
      (snapshot) => {
        // documentId in progress
        //   documentId.progress = (documentIdTask.snapshot.bytesTransferred / documentIdTask.snapshot.totalBytes) * 100;
      },
      (error) => {
        // documentId failed
        console.log(error)
      },
      () => {
        // documentId success
        this.auth.auth.currentUser.updateProfile({
          displayName: this.auth.auth.currentUser.displayName,
          photoURL: profilePhotoTask.snapshot.downloadURL
        });
        //this.saveFileData(this.photoIdentity);
        console.log(" Profile Upload");
      }
    );


  }

  detectGovernmentIdFile(event) {
    this.selectedFile = event.target.files[0];
    let file = this.selectedFile;
    this.photoIdentity = new PhotoIdentity(file);

    let storageRef = firebase.storage().ref();

    let photoIdentityTask = storageRef.child(`${this.basePath}/${this.id}`).put(this.photoIdentity.file);

    photoIdentityTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
      (snapshot) => {
        // documentId in progress
        //   documentId.progress = (documentIdTask.snapshot.bytesTransferred / documentIdTask.snapshot.totalBytes) * 100;
      },
      (error) => {
        // documentId failed
        console.log(error)
      },
      () => {
        // documentId success
        this.db.object(`/profiles/` + this.id).update({ photoIdentity: photoIdentityTask.snapshot.downloadURL });
        //this.saveFileData(this.photoIdentity);
        console.log("Document Upload");
      }
    );
  }

  gotoReviews() {
    this.navCtrl.push(ReviewsPage, { userId: this.id });
  }

}

 

Accessing login template

<ion-header>
  <ion-navbar>
    <ion-title>Profile</ion-title>
    <ion-buttons left>
      <button ion-button menuToggle="profileMenu">
        <ion-icon name="menu"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content>
  <div *ngIf=userCheck>
    <ion-card padding>
      <ion-card-content>
        <img src={{photoURL}}/>
        <br/>
        <label for="file">Edit Profile Photo</label>
        <input type="file" (change)="detectProfileFile($event)">
      </ion-card-content>
      <ion-item>
        <ion-icon ion-icon ios="ios-mail" md="md-mail" color="primary" item-left></ion-icon>
        <p>{{email}}</p>
      </ion-item>
    </ion-card>
    <ion-card>
      <ion-item color="primary">Profile Information
        <button ion-button outline (click)="editProfile(id)" class="editProfileBtn" right>Edit Profile</button>
      </ion-item>
      <ion-item>
        <p>
          <b>User Name : </b>{{profileRef.firstName}} {{profileRef.lastName}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>DOB : </b> {{profileRef.dob}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Gender : </b>{{profileRef.gender}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Location : </b>{{profileRef.location}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>School : </b>{{profileRef.school}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Language : </b>{{profileRef.language}}</p>
      </ion-item>
    </ion-card>
    <ion-card>
      <ion-item color="primary">Company Details
        <button ion-button outline (click)="addAdditionalInfo(id)" class="editProfileBtn" right>Edit Additional Details</button>
      </ion-item>
      <ion-item>
        <p>
          <b>Company Name : </b> {{profileRef.Company}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Job Nature : </b>{{profileRef.jobNature}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Company Email : </b>{{profileRef.workEmail}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Company Address : </b>{{profileRef.workAddress}}</p>
      </ion-item>
      <ion-item>
        <p>
          <b>Company Phone : </b>{{profileRef.workPhone}}</p>
      </ion-item>
      <div>
        <div *ngIf="profileRef.photoIdentity; then govId else newGovId" class="govID"></div>
        <ng-template #govId>
          <ion-item>
            <h2>Government Identity Card </h2>
            <img src={{profileRef.photoIdentity}}>
          </ion-item>
        </ng-template>
        <ng-template #newGovId>
          <ion-item>
            <h2>Upload Government Id </h2>
            <label>
              <input type="file" (change)="detectGovernmentIdFile($event)">
            </label>
          </ion-item>
        </ng-template>
      </div>
    </ion-card>
    <ion-card>
      <ion-item>
        <button block ion-button (click)="gotoReviews()">Recent reviews</button>
      </ion-item>
      <ion-item>
        <button block ion-button (click)="logout()">Logout</button>
      </ion-item>
    </ion-card>
  </div>
  <div padding *ngIf=!userCheck>
    <ion-card>
      <ion-item>
        <h2>Welcome, Guest</h2>
      </ion-item>
      <ion-item>
        <h2>Already registered?</h2>
        <button block ion-button (click)="login()">Login</button>
      </ion-item>
      <ion-item>
        <h2>Don't have an account?</h2>
        <button block ion-button (click)="register()">Register</button>
      </ion-item>
    </ion-card>
  </div>
</ion-content>

Angular Js update to Db

'use strict';
angular.module('app')
    .controller('MyAccountController', function ($scope, $timeout, $stateParams, $window, $http, $noty, $state, $q, $i18next) {
        if (Storages.sessionStorage.isEmpty('profile')) {
            $http.get('/api/profile').then(function (res) {
                Storages.sessionStorage.set('profile', res.data.data);
                $scope.data = res.data.data;
            }, function () {
                $noty({
                    layout: 'bottom',
                    type: 'error',
                    timeout: 5000,
                    maxVisible: 1,
                    killer: true,
                    text: $i18next.t('angularjs.myprofile.loadError')
                });
            });
        } else {
            $scope.data = Storages.sessionStorage.get('profile');
        }

        $scope.save = function () {
            $scope.isHttp = true;

            $http.post('/api/profile', {profile: $scope.data}).then(function (res) {
                if (window.config.app.debug) console.log(res);
                Storages.sessionStorage.set('profile', $scope.data);
                $noty({
                    layout: 'bottom',
                    type: 'success',
                    timeout: 5000,
                    maxVisible: 1,
                    killer: true,
                    text: $i18next.t('angularjs.myprofile.updatedError')
                });
                $scope.isHttp = false;
            }, function () {
                $noty({
                    layout: 'bottom',
                    type: 'error',
                    timeout: 5000,
                    maxVisible: 1,
                    killer: true,
                    text: $i18next.t('angularjs.myprofile.loadError')
                });
                $scope.isHttp = false;
            });

        };
    });

 

Setting Storage session
—————————

Storages.sessionStorage.set(‘profile’, res.data.data);

$scope.data = Storages.sessionStorage.get(‘profile’);

Ajax

AJAX, also known as Asynchronous JavaScript and XML, is a technology that allows the applications to send and retrieve data from the server asynchronously, without refreshing the page.

The AngularJS $http service makes a request to the server and returns a response.
The $http service wraps the low-level interaction with the XMLHttpRequest object, providing an easy way to perform calls. This service could be called by just passing a configuration object, used to set a lot of important information such as the method, the URL of the requested resource, the data to be sent, and many others:

$http({method: “GET”, url: “/resource”});

It also returns a promise that we can attach the success and error behavior to this promise:

$http.get(url: "/resource"}) 
.then( function(payload){
  //Success code
  }, function(mg) {

To make it easier to use, the following shortcut methods are available for this service. In this case, the configuration object is optional:

$http.get(url, [config]) 
$http.post(url, data, [config]) 
$http.put(url, data, [config]) 
$http.head(url, [config]) 
$http.delete(url, [config]) 
$http.jsonp(url, [config])

Note: The $http service is the easiest way to send AJAX calls to your web server. Remember, that AJAX calls cannot be sent to a different domain than the domain from which the HTML page making the AJAX calls is loaded.

In Example below, we are getting student data from a remote file through $https service. AngularJS needs data in JSON format.
Screenshot of our application on Ajax call. 

Step 1: First create a file called students.json in data folder in our root application and add following code. 

[
  {
    "Name" : "Vikash Sharma",
    "RollNo" : 201,
    "Percentage" : "80%"
  },{
    "Name" : "Arjun Singh",
    "RollNo" : 202,
    "Percentage" : "90%"
  },{
    "Name" : "Anu Malik",
    "RollNo" : 203,
    "Percentage" : "50%"
  }, {
      "Name" : "Anil Tingtong",
      "RollNo" : 204,
      "Percentage" : "60%"
    }
]

Step 2: Create a file containing our template and AngularJS application with a single $http AJAX example: 

<html ng-app="ajaxApp">
<script src="js/angular.min.js"></script>
<body ng-controller="myCtrl">
 <button ng-click="getStudents()">Get Students</button>
 <hr>
 <table border=1>
   <tr>
     <th>Roll No</th> <th>Name </th> <th>Precentage</th>
   </tr>
   <tr ng-repeat="s in students">
      <td>{{ s.RollNo}}</td>  <td> {{ s.Name }}</td> <td> {{ s.Percentage }}</td>
   </tr>
 </table>
  <script>
  var app = angular.module("ajaxApp", [])
  .controller("myCtrl", function($scope, $http){
    $scope.students = [];
    $scope.getStudents = function() {
      var url = "data/students.json";
      $http.get(url)
      .then( function(payload){
        $scope.students = payload.data;
      }, function(msg) {
        alert("Sorry we can't access the ajax data");
      });
    };
  });

</script>
</body>
</html>

 

ng-value for Radio button

The ng-value is most used under ng-repeat ngValue is useful when dynamically generating lists of radio buttons using ngRepeat. 

	<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
</head>
<body>
<form ng-controller="myCtrl">
<h2>Which is your favorite Cartoon ?</h2>
<label ng-repeat="name in names" for="{{name}}">
<input type="radio" ng-model="my.favorite" ng-value="name"> {{name}}
</label>
<div>You chose {{my.favorite}}</div>
</form>
<script>
angular.module('myApp', [])
.controller("myCtrl", function($scope){
$scope.names = ['Popeye', 'Superman', 'Scrappy-Doo', 'Donald Duck'];
$scope.my = { favorite: '' };
});
</script>
</body>
<html>

Tabs in AngularJs

The Angularjs doesn’t have a directive to serves as tabs. We can easily create tabs, each tab contains different information associated with each tab button.
In this tutorial we are creating simple tabs contenting four tabs button and clicking on each will display its corresponding data and hide other unclicked tabs contents.

Screenshot  of our apps. 

Add following code in our template file let say tabs.html
<!DOCTYPE html>
<html ng-app="tabApp">
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="js/angular.min.js"></script>
<style>
li::after {
  content: " | ";
}
 li.active > a{
  background-color: red;
  color:white;
  border-radius: 2px;
  margin:1em;
  padding: 0.2em;
}
</style>
<body>
  <div class="container">
    <div ng-controller="TabController">
      <ul class="breadcrumb">
        <li ng-class="{ active: isSet(1) }"><a href ng-click="setTab(1)">Profile</a></li>
        <li ng-class="{ active: isSet(2) }"><a href ng-click="setTab(2)">Friend</a></li>
        <li ng-class="{ active: isSet(3) }"><a href ng-click="setTab(3)">Privacy</a></li>
        <li ng-class="{ active: isSet(4) }"><a href ng-click="setTab(4)">Chat </a></li>
      </ul>
      <div ng-show="isSet(1)">
        <p>Tab contenting the profile Information</p>
      </div>
      <div ng-show="isSet(2)">
        <p>Tab contenting the Friends Information</p>
      </div>
      <div class="block-friends" ng-show="isSet(3)">
        <p>Tab contenting the privacy Information</p>
      </div>
      <div class="block-friends" ng-show="isSet(4)">
        <p>Tab contenting the Chat Information</p>
      </div>
    </div>
  </div>
  <script>
  angular.module('tabApp', [])
    .controller('TabController', function($scope) {
      $scope.tab = 1;

      $scope.setTab = function(newTab){
        $scope.tab = newTab;
      };

      $scope.isSet = function(tabNum){
        return $scope.tab === tabNum;
      };
  });
  </script>
</body>
</html>

Provider

The provider is like a service that generates a factory. We can also create service as a provider. if that makes sense. During initialization, you can configure a provider to act a certain way after the application has loaded. The $http service is really a provider, and you can configure its defaults during initialization if you wish.

A provider returns nothing, but defines this.$get(); a function to return a factory-like object. When you define provider Test, you’re really defining TestProvider in config() ; the thing returned from this.$get is really Foo in a controller.

When should we use the provider?
1. We can use a provider to configure or set some value to configuration through config()
2. We can use our provider to a controller

The angular.module() has a function config(), which lets us configure a module, we can use a provider to set/initialize some value to config() method. We can use a provider to set parts of the service before the service can be consumed. Where config() is prototype method and is executed only one time in the application lifecycle. We can use a provider to set API configuration. Once the application is load, configuration get executed and whatever the data we configure in this config() function is shared inside our application.

The $route service is a good example of it. We use the underlying $routeProvider to configure the routes before they can be used in the app. We can use a provider to give the end user an option to set some default value, the default value can be used by other methods too.

The provider can be implemented by $get in a controller and any other in config. Whatever implement we have defined in $get of the provider can only be accessed by a controller and those implementations which are outside $get can be accessed by the controller.

Note: Referencing of a provider in controller and config have differed. In a controller, we can use provider reference as provider name in a controller. When using provider inside the config() method we have to use provider reference as providerName+Provider that is serviceProvider in our example below. 

Note: We can’t use a function of the provider which is defined outside $get the implementation of the provider inside our controller. This means whatever function that is defined inside the $get of the provider can access inside our controller by using provider reference. Eg // service.setValue(a); we can use this service method in our controller.

<html ng-app="myApp">
<html>
<script src="js/angular.min.js"></script>
<body ng-controller="myCtrl">
<div >
  Enter a Number <input type="number" ng-model="num"/><br/><br/>
  <button ng-click="getSquare(num)">Get square </button> | <button ng-click="getFactorial(num)">Get Factorial </button><br/><br/>
  Result : {{ result}}
</div>

<script>
  var app = angular.module("myApp", [])
  .provider("service", function() {

    var apiKey = '';
    this.setApiKey = function(value){
      apiKey = value;
    };

    this.$get = function(){
      var obj = {};
      obj.square = function(a){
        return a * a;
      };
      obj.factorial = function(a){
        var result = 1;
        for( var i = a; i > 0; i --){
          result *= i;
        }
        return result;
      };
      return obj;
    };
  })
  .config(function(serviceProvider){
     serviceProvider.setApiKey(35445);
  })
  .controller("myCtrl", function($scope, service){
      $scope.a = 0;
      $scope.result = 0;

      $scope.getSquare = function(a) {
      //  service.setValue(a);
        $scope.result = service.square(a);
      };

      $scope.getFactorial = function(a){
        $scope.result = service.factorial(a);
      };
  });
</script>
</body>
</html>

 

Custom Filter

Angular has a .filter() method for each Module, which means we can write our own custom filters.
The returned function gets invoked each time Angular calls the filter, which means two-way binding for our filters. The user makes a change, the filter runs again and updates as necessary. The name of our filter is how we can reference it inside Angular bindings.
This article represents high-level concepts and code sample/example of how to create a custom filter. How to Create A Custom Filter and in this example, we are using a custom filter to reverse the string and convert the reverse string in lower case. 

To create a new filter, the filter needs to be registered as a new factory function with your module. In the example below, “reverse” filter is registered with “myApp” module using the “filter” factory function.

Example 1: Here we are creating a custom filter to reverse the string and convert the reverse string in lower case. 

<html ng-app="myApp">
<html>
<script src="js/angular.min.js"></script>
<body>
  <h3>Custom filter to reverse a string</h3>
  <input type="text" ng-model="str"><br/>
  Orginal input type string : {{ str }} <br/>

  Reverse of string in lower case : {{ str | reverse : 'lowercase' }}
  <script>
  var app = angular.module("myApp", [])
  .filter("reverse", function () {
    return function(text, option) {
      text = text || '';
      var reverseStr = '';
      for(var i = text.length -1; i >= 0; i--){
        reverseStr += text[i];
      }
      if(option){
        if(option.toUpperCase() == 'UPPERCASE'){
          return reverseStr.toUpperCase();
        } else if (option.toUpperCase() == 'LOWERCASE'){
          return reverseStr.toLowerCase();
        }
      }
    //  return reverseStr;
    };
  })
</script>
</body>
</html>

Example 2:  Filter for ng-repeat, in example 2 we will create a custom filter to display all the name of all friends starts with A. 

<html ng-app="myApp">
<html>
<script src="js/angular.min.js"></script>
<body>
  <div>
      <div ng-controller="PersonCtrl as person">
          <ol>
              <li ng-repeat="friend in person.friends | startsWithA">
                  {{ friend }}
              </li>
          </ol>
      </div>
  </div>
<script>
var app = angular.module('myApp', []);

app.filter('startsWithA', function () {
    return function (items) {
        var filtered = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            if (/a/i.test(item.name.substring(0, 1))) {
                filtered.push(item);
            }
        }
        return filtered;
    };
});

app.controller('PersonCtrl', function () {
    this.friends = [{
        name: 'Alex'
    }, {
        name: 'Smith'
    }, {
        name: 'Arjun'
    }, {
        name: 'Arien'
    }, {
        name: 'Jim'
    }];
});

</script>
</body>
</html>

Filter

In AngularJS, filters are used to format data. Filters are really useful when we need to format dates and currency according to our current locale, or even when we need to support the filtering feature of a grid component. They are the perfect solution to easily perform any data manipulation.

Filters associated with other technologies, like directives and expressions, are responsible for the extraordinary expressiveness of the framework. They allow us to easily manipulate and transform any value, we can combined filter with expressions inside a template, we can also be injected filter in other components such as controllers and services.

The framework already brings with it a set of ready-to-use filters that can be quite useful in your daily development. Now, let’s have a look at the different types of AngularJS filters.

Filter              Description
Currency       It formats a number to a currency format.
Date                It formats a date to a specified format.
Filter              It select a subset of items from an array.
Json                It formats an object to a JSON string.
Limit              It is used to limit an array/string, into a specified number of elements/characters.
Lowercase    It formats a string to lower case.
Number         It formats a number to a string.
Orderby         It orders an array by an expression.
Uppercase     It formats a string to upper case.

Basic usage with expressions
To make filters interact with the expression, we just need to put them inside double curly brackets:
{{expression | filter}}

Example:
Date filter   <p>{{ 1400956671914 | date: ‘dd-MM-yyyy’ }}</p>

Output in browser
<p>24-05-2014</p>

Also, the filters can be combined, thus creating a chain where the output of filter1 is the input of filter2, which is similar to the pipeline that exists in the shell of Unix-based operating systems:
{{expression | filter1 | filter2}}

Note: The state change in the filter are temporary and model object data is not changed permanently.

The currency filter is used to format a number based on a currency. The basic usage of this filter is without any parameter:
{{ 10 | currency}}
The result of the evaluation will be the number $10.00, formatted and prefixed with the dollar sign as default. We can also apply a specific locale symbol,

Fee structure : {{ student.qty * student.amount | currency : “&#8377;” }}
Fee structure: ₹4,000.00

in an example, below we had using the filter of uppercase, currency and search filter to display the matching list from countries code object and used order to sort in increasing and decreasing. 

<html ng-app="myApp">
<html>
<script src="js/angular.min.js"></script>
<body ng-controller="myCtrl">
<div >
  <table border="1">
    <tr>
      <td> First Name :  </td>
      <td>{{ student.firstName | uppercase }} </td>
    </tr>
    <tr>
      <td> Last Name :  </td>
      <td>{{ student.lastName | lowercase }} </td>
    </tr>
    <tr>
      <td> Id </td>
      <td> {{ student.id }} </td>
    </tr>
    <tr>
      <td> Full Name : </td>
      <td> {{ student.fullName()}} </td>
    </tr>
    <tr>
      <td> Fee structure : </td>
      <td>{{ student.qty * student.amount | currency : "₹" }} </td>  // display local currency
    </tr>
    <tr><th colspan="2">COUNTRIES</th></tr>
    <tr>
      <th colspan="2"><input type="text" ng-model="searchText" placeholder="Enter filter search">  </th>
    </tr>
    <tr ng-repeat="country in Countries | filter: searchText | orderBy: '-name'">
//search filter
      <td> {{ country.name }} </td>
      <td>{{ country.code }}</td>
    </tr>
  </table>
</div>

<script>
  var app = angular.module("myApp", []);
  app.controller("myCtrl", function($scope){
    $scope.student = {
      firstName : "Arjun",
      lastName : "Smith",
      id : 110,
      fullName : function(){
        return $scope.student.firstName + " " + $scope.student.lastName;
      },
      qty: 20,
      amount: 200
    };

    $scope.Countries = [
        {"name": "Afghanistan", "code": "AF"},
        {"name": "land Islands", "code": "AX"},
        {"name": "Albania", "code": "AL"},
        {"name": "Algeria", "code": "DZ"},
        {"name": "American Samoa", "code": "AS"},
        {"name": "AndorrA", "code": "AD"},
        {"name": "Angola", "code": "AO"},
        {"name": "Anguilla", "code": "AI"},
        {"name": "Antarctica", "code": "AQ"},
        {"name": "Antigua and Barbuda", "code": "AG"},
        {"name": "Argentina", "code": "AR"},
        {"name": "Armenia", "code": "AM"},
        {"name": "Aruba", "code": "AW"},
        {"name": "Australia", "code": "AU"},
        {"name": "Austria", "code": "AT"},
        {"name": "Azerbaijan", "code": "AZ"},
        {"name": "Bahamas", "code": "BS"},
        {"name": "Bahrain", "code": "BH"},
        {"name": "Bangladesh", "code": "BD"},
        {"name": "Barbados", "code": "BB"},
        {"name": "Belarus", "code": "BY"},
        {"name": "Belgium", "code": "BE"},
        {"name": "Belize", "code": "BZ"},
        {"name": "Benin", "code": "BJ"},
        {"name": "Bermuda", "code": "BM"},
        {"name": "Bhutan", "code": "BT"},
        {"name": "Bolivia", "code": "BO"},
        {"name": "Bosnia and Herzegovina", "code": "BA"},
        {"name": "Botswana", "code": "BW"},
        {"name": "Bouvet Island", "code": "BV"},
        {"name": "Brazil", "code": "BR"},
        {"name": "British Indian Ocean Territory", "code": "IO"},
        {"name": "Brunei Darussalam", "code": "BN"},
        {"name": "Bulgaria", "code": "BG"},
        {"name": "Burkina Faso", "code": "BF"},
        {"name": "Burundi", "code": "BI"},
        {"name": "Cambodia", "code": "KH"},
        {"name": "Cameroon", "code": "CM"},
        {"name": "Canada", "code": "CA"},
        {"name": "Cape Verde", "code": "CV"},
        {"name": "Cayman Islands", "code": "KY"},
        {"name": "Central African Republic", "code": "CF"},
        {"name": "Chad", "code": "TD"},
        {"name": "Chile", "code": "CL"},
        {"name": "China", "code": "CN"},
        {"name": "Christmas Island", "code": "CX"},
        {"name": "Cocos (Keeling) Islands", "code": "CC"},
        {"name": "Colombia", "code": "CO"},
        {"name": "Comoros", "code": "KM"},
        {"name": "Congo", "code": "CG"},
        {"name": "Congo, The Democratic Republic of the", "code": "CD"},
        {"name": "Cook Islands", "code": "CK"},
        {"name": "Costa Rica", "code": "CR"},
        {"name": "Cote D\"Ivoire", "code": "CI"},
        {"name": "Croatia", "code": "HR"},
        {"name": "Cuba", "code": "CU"},
        {"name": "Cyprus", "code": "CY"},
        {"name": "Czech Republic", "code": "CZ"},
        {"name": "Denmark", "code": "DK"},
        {"name": "Djibouti", "code": "DJ"},
        {"name": "Dominica", "code": "DM"},
        {"name": "Dominican Republic", "code": "DO"},
        {"name": "Ecuador", "code": "EC"},
        {"name": "Egypt", "code": "EG"},
        {"name": "El Salvador", "code": "SV"},
        {"name": "Equatorial Guinea", "code": "GQ"},
        {"name": "Eritrea", "code": "ER"},
        {"name": "Estonia", "code": "EE"},
        {"name": "Ethiopia", "code": "ET"},
        {"name": "Falkland Islands (Malvinas)", "code": "FK"},
        {"name": "Faroe Islands", "code": "FO"},
        {"name": "Fiji", "code": "FJ"},
        {"name": "Finland", "code": "FI"},
        {"name": "France", "code": "FR"},
        {"name": "French Guiana", "code": "GF"},
        {"name": "French Polynesia", "code": "PF"},
        {"name": "French Southern Territories", "code": "TF"},
        {"name": "Gabon", "code": "GA"},
        {"name": "Gambia", "code": "GM"},
        {"name": "Georgia", "code": "GE"},
        {"name": "Germany", "code": "DE"},
        {"name": "Ghana", "code": "GH"},
        {"name": "Gibraltar", "code": "GI"},
        {"name": "Greece", "code": "GR"},
        {"name": "Greenland", "code": "GL"},
        {"name": "Grenada", "code": "GD"},
        {"name": "Guadeloupe", "code": "GP"},
        {"name": "Guam", "code": "GU"},
        {"name": "Guatemala", "code": "GT"},
        {"name": "Guernsey", "code": "GG"},
        {"name": "Guinea", "code": "GN"},
        {"name": "Guinea-Bissau", "code": "GW"},
        {"name": "Guyana", "code": "GY"},
        {"name": "Haiti", "code": "HT"},
        {"name": "Heard Island and Mcdonald Islands", "code": "HM"},
        {"name": "Holy See (Vatican City State)", "code": "VA"},
        {"name": "Honduras", "code": "HN"},
        {"name": "Hong Kong", "code": "HK"},
        {"name": "Hungary", "code": "HU"},
        {"name": "Iceland", "code": "IS"},
        {"name": "India", "code": "IN"},
        {"name": "Indonesia", "code": "ID"},
        {"name": "Iran, Islamic Republic Of", "code": "IR"},
        {"name": "Iraq", "code": "IQ"},
        {"name": "Ireland", "code": "IE"},
        {"name": "Isle of Man", "code": "IM"},
        {"name": "Israel", "code": "IL"},
        {"name": "Italy", "code": "IT"},
        {"name": "Jamaica", "code": "JM"},
        {"name": "Japan", "code": "JP"},
        {"name": "Jersey", "code": "JE"},
        {"name": "Jordan", "code": "JO"},
        {"name": "Kazakhstan", "code": "KZ"},
        {"name": "Kenya", "code": "KE"},
        {"name": "Kiribati", "code": "KI"},
        {"name": "Korea, Democratic People\"S Republic of", "code": "KP"},
        {"name": "Korea, Republic of", "code": "KR"},
        {"name": "Kuwait", "code": "KW"},
        {"name": "Kyrgyzstan", "code": "KG"},
        {"name": "Lao People\"S Democratic Republic", "code": "LA"},
        {"name": "Latvia", "code": "LV"},
        {"name": "Lebanon", "code": "LB"},
        {"name": "Lesotho", "code": "LS"},
        {"name": "Liberia", "code": "LR"},
        {"name": "Libyan Arab Jamahiriya", "code": "LY"},
        {"name": "Liechtenstein", "code": "LI"},
        {"name": "Lithuania", "code": "LT"},
        {"name": "Luxembourg", "code": "LU"},
        {"name": "Macao", "code": "MO"},
        {"name": "Macedonia, The Former Yugoslav Republic of", "code": "MK"},
        {"name": "Madagascar", "code": "MG"},
        {"name": "Malawi", "code": "MW"},
        {"name": "Malaysia", "code": "MY"},
        {"name": "Maldives", "code": "MV"},
        {"name": "Mali", "code": "ML"},
        {"name": "Malta", "code": "MT"},
        {"name": "Marshall Islands", "code": "MH"},
        {"name": "Martinique", "code": "MQ"},
        {"name": "Mauritania", "code": "MR"},
        {"name": "Mauritius", "code": "MU"},
        {"name": "Mayotte", "code": "YT"},
        {"name": "Mexico", "code": "MX"},
        {"name": "Micronesia, Federated States of", "code": "FM"},
        {"name": "Moldova, Republic of", "code": "MD"},
        {"name": "Monaco", "code": "MC"},
        {"name": "Mongolia", "code": "MN"},
        {"name": "Montenegro", "code": "ME"},
        {"name": "Montserrat", "code": "MS"},
        {"name": "Morocco", "code": "MA"},
        {"name": "Mozambique", "code": "MZ"},
        {"name": "Myanmar", "code": "MM"},
        {"name": "Namibia", "code": "NA"},
        {"name": "Nauru", "code": "NR"},
        {"name": "Nepal", "code": "NP"},
        {"name": "Netherlands", "code": "NL"},
        {"name": "Netherlands Antilles", "code": "AN"},
        {"name": "New Caledonia", "code": "NC"},
        {"name": "New Zealand", "code": "NZ"},
        {"name": "Nicaragua", "code": "NI"},
        {"name": "Niger", "code": "NE"},
        {"name": "Nigeria", "code": "NG"},
        {"name": "Niue", "code": "NU"},
        {"name": "Norfolk Island", "code": "NF"},
        {"name": "Northern Mariana Islands", "code": "MP"},
        {"name": "Norway", "code": "NO"},
        {"name": "Oman", "code": "OM"},
        {"name": "Pakistan", "code": "PK"},
        {"name": "Palau", "code": "PW"},
        {"name": "Palestinian Territory, Occupied", "code": "PS"},
        {"name": "Panama", "code": "PA"},
        {"name": "Papua New Guinea", "code": "PG"},
        {"name": "Paraguay", "code": "PY"},
        {"name": "Peru", "code": "PE"},
        {"name": "Philippines", "code": "PH"},
        {"name": "Pitcairn", "code": "PN"},
        {"name": "Poland", "code": "PL"},
        {"name": "Portugal", "code": "PT"},
        {"name": "Puerto Rico", "code": "PR"},
        {"name": "Qatar", "code": "QA"},
        {"name": "Reunion", "code": "RE"},
        {"name": "Romania", "code": "RO"},
        {"name": "Russian Federation", "code": "RU"},
        {"name": "RWANDA", "code": "RW"},
        {"name": "Saint Helena", "code": "SH"},
        {"name": "Saint Kitts and Nevis", "code": "KN"},
        {"name": "Saint Lucia", "code": "LC"},
        {"name": "Saint Pierre and Miquelon", "code": "PM"},
        {"name": "Saint Vincent and the Grenadines", "code": "VC"},
        {"name": "Samoa", "code": "WS"},
        {"name": "San Marino", "code": "SM"},
        {"name": "Sao Tome and Principe", "code": "ST"},
        {"name": "Saudi Arabia", "code": "SA"},
        {"name": "Senegal", "code": "SN"},
        {"name": "Serbia", "code": "RS"},
        {"name": "Seychelles", "code": "SC"},
        {"name": "Sierra Leone", "code": "SL"},
        {"name": "Singapore", "code": "SG"},
        {"name": "Slovakia", "code": "SK"},
        {"name": "Slovenia", "code": "SI"},
        {"name": "Solomon Islands", "code": "SB"},
        {"name": "Somalia", "code": "SO"},
        {"name": "South Africa", "code": "ZA"},
        {"name": "South Georgia and the South Sandwich Islands", "code": "GS"},
        {"name": "Spain", "code": "ES"},
        {"name": "Sri Lanka", "code": "LK"},
        {"name": "Sudan", "code": "SD"},
        {"name": "Suriname", "code": "SR"},
        {"name": "Svalbard and Jan Mayen", "code": "SJ"},
        {"name": "Swaziland", "code": "SZ"},
        {"name": "Sweden", "code": "SE"},
        {"name": "Switzerland", "code": "CH"},
        {"name": "Syrian Arab Republic", "code": "SY"},
        {"name": "Taiwan, Province of China", "code": "TW"},
        {"name": "Tajikistan", "code": "TJ"},
        {"name": "Tanzania, United Republic of", "code": "TZ"},
        {"name": "Thailand", "code": "TH"},
        {"name": "Timor-Leste", "code": "TL"},
        {"name": "Togo", "code": "TG"},
        {"name": "Tokelau", "code": "TK"},
        {"name": "Tonga", "code": "TO"},
        {"name": "Trinidad and Tobago", "code": "TT"},
        {"name": "Tunisia", "code": "TN"},
        {"name": "Turkey", "code": "TR"},
        {"name": "Turkmenistan", "code": "TM"},
        {"name": "Turks and Caicos Islands", "code": "TC"},
        {"name": "Tuvalu", "code": "TV"},
        {"name": "Uganda", "code": "UG"},
        {"name": "Ukraine", "code": "UA"},
        {"name": "United Arab Emirates", "code": "AE"},
        {"name": "United Kingdom", "code": "GB"},
        {"name": "United States", "code": "US"},
        {"name": "United States Minor Outlying Islands", "code": "UM"},
        {"name": "Uruguay", "code": "UY"},
        {"name": "Uzbekistan", "code": "UZ"},
        {"name": "Vanuatu", "code": "VU"},
        {"name": "Venezuela", "code": "VE"},
        {"name": "Viet Nam", "code": "VN"},
        {"name": "Virgin Islands, British", "code": "VG"},
        {"name": "Virgin Islands, U.S.", "code": "VI"},
        {"name": "Wallis and Futuna", "code": "WF"},
        {"name": "Western Sahara", "code": "EH"},
        {"name": "Yemen", "code": "YE"},
        {"name": "Zambia", "code": "ZM"},
        {"name": "Zimbabwe", "code": "ZW"}
      ];
  });
</script>
</body>
</html>

Sharing data between Controller

Angularjs doesn’t allow the controller to define in another controller. “How do we achieved nesting controller and shared data between the nested controllers in AngularJS?”

At the time of implementation, even we made implementation of each controller separately and no relation between each controller. When we are binding this controller into the view, we define one controller within another only in view it becomes the as nested controller and has a relationship of parent and child.

  <div ng-controller="myCtrl1 as c1" >
    Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
    <div ng-controller="myCtrl2" >
      Controller 2 Message Date : <input type="text" ng-model="c1.msg"/>
    </div>
  </div>

 

We can easily access data model the of a parent in child controller and updating data model of parent will reflect in its child controller.

Problem: We will have a problem when updating data from child to parent. When specific data model is updated in the child, the data model will not be updated in parents. If a model object doesn’t have any kind of prototype reference then it will try to update data at scope level and even the data is defined at the parent or root scope. We need to define prototype for data model in controller and prototype is kind of reference. How to define prototype when it comes to scope object. We have a different approach to this problems.

1. Controller Aliasing
We can give an alias name to controller binding. We can give an alias name to myCtrl 1 as c1. As now c1 is acting as kind of prototype. When we are updating the data model object of a parent in child controller and the update will reflect in the parent. In this case, we are not creating in the model object while editing parent model in child and we are editing only parent model through aliasing. If we are not using aliasing method then editing msg in controller two will create it own msg data model at its own scope object. 

<html ng-app="myApp">
<html>
<head>
  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1 as c1" >
    Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
    <div ng-controller="myCtrl2" >
      Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      <div ng-controller="myCtrl3" >
        Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])

  .controller("myCtrl1", function($scope){
    var c1 = this;
    c1.msg = "My controller 1 msg";
  })

  .controller("myCtrl2", function($scope){
  })

  .controller("myCtrl3", function($scope){
  })

</script>
</body>
</html>

Second Methods: Accessing through a JSON object. In this method, we will remove c1 in ng-controller of myCtrl1. We have to define $Scope.c1 as JSON object in controller one and in view we can access the model through c1.msg.

<html ng-app="myApp">
<html>
<head>

  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1" >
    Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
    <div ng-controller="myCtrl2" >
      Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      <div ng-controller="myCtrl3" >
        Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])
  .controller("myCtrl1", function($scope){
    $scope.c1 = {
      msg : "My controller 1 msg"
    }
  })
  .controller("myCtrl2", function($scope){
  })
  .controller("myCtrl3", function($scope){
  })
</script>
</body>
</html>

Method 3rd:
When we tried to update the specific model object data at a respective child the AngualarJs is creating an isolated model in respective child controller.
We can be solved this issue by using another method by using $parent.

<input type=”text” ng-model=”$parent.msg”/>

Where $parent is a prototype and here we are informing AngualarJs not to look model object at a respective child and asking AngualarJs to look model object at its parent reference when we are updating the model object at
a respective child.

All above methods will not create any isolated model object at it child controller when a child controller update model object of its parents. 

<html ng-app="myApp">
<html>
<head>
  <style>
    div {
      border : 1px solid blue;
      padding: 10px;
      margin: 10px;
    }
  </style>
  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1" >
    Controller 1 Message Date : <input type="text" ng-model="msg"/>
    <div ng-controller="myCtrl2" >
      Controller 2 Message Date : <input type="text" ng-model="$parent.msg"/>
      <div ng-controller="myCtrl3" >
        Controller 2 Message Date : <input type="text" ng-model="$parent.$parent.msg"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])
  .controller("myCtrl1", function($scope){
    $scope.msg = "My controller 1 msg";
  })
  .controller("myCtrl2", function($scope){
  })
  .controller("myCtrl3", function($scope){
  })
</script>
</body>
</html>

In controller 3 we have to use the double $parent to informing AngularJs to look model of parents parents. It will be difficult for when we have many levels of parent-child relationship.

Methods 4: Using $broadcast and $emit
Using these two we can send information or signal from source to destination controller. We have to define particular source and destination in this methods with respect to nesting. So when it comes to the broadcast source will be parent and destination is a child.

$broadcast: parent to child
$emit : child to parent

In this example when updating data model at a child will create an isolated model at it a child, we have to inform the parent that updating model object at child myCtrl3, the data model object at the parent have to updated in its parent myCtrl2 and its parent myCtrl1.

<html ng-app="myApp">
<html>
<head>
  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1" >
    Controller 1 Message Date : <input type="text" ng-model="msg" ng-keyup="toChild()"/>
    <div ng-controller="myCtrl2" >
      Controller 2 Message Date : <input type="text" ng-model="msg"  ng-keyup="toParentAndChild()" />
      <div ng-controller="myCtrl3" >
        Controller 2 Message Date : <input type="text" ng-model="msg" ng-keyup="toParent()"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])
  .controller("myCtrl1", function($scope){
    $scope.msg = "My controller 1 msg";

    $scope.toChild = function(){
      $scope.$broadcast("toChild", $scope.msg);
    }
    $scope.$on("toParent", function(event, data){
      $scope.msg = data;
    })

  })
  .controller("myCtrl2", function($scope){
    $scope.toParentAndChild = function(){
      $scope.$emit("toParent", $scope.msg);
      $scope.$broadcast("toChild", $scope.msg);
    };
    $scope.$on("toParent", function(event, data){
      $scope.msg = data;
    });

    $scope.$on("toChild", function(event, data){
      $scope.msg = data;
    })
  })
  .controller("myCtrl3", function($scope){
    $scope.toParent = function(){
      $scope.$emit("toParent", $scope.msg);
    }

  })
</script>
</body>
</html>

We have four methods of updating data model from child to parent, the last methods $broadcast and $emit is slow in performance as update data at controller and pass the information between controller. If we can solve problem when updating data from child to parent with aliasing and $scope.parent then it right choice to do in my opinion.