Skip to content

Instantly share code, notes, and snippets.

@alemohamad
Last active August 29, 2015 14:26
Show Gist options
  • Save alemohamad/7787393da95b996245a4 to your computer and use it in GitHub Desktop.
Save alemohamad/7787393da95b996245a4 to your computer and use it in GitHub Desktop.

AngularJS

This covers the 1.2.x to 1.4.x versions.

Views, Controllers and built-in Directives

app.controller('MainController', function($scope, $timeout) {
  $timeout(function() {
    // the equivalent of setTimeout, but better in AngularJS
  }, 3000)
})

Filters

 <button ng-click="inc()">Click me</button>
 <h2 ng-show="even">even</h2>
 <h2 ng-hide="even">odd</h2>
 <input ng-model="myfilter.name">

 <div ng-repeat="user in mydata.arr | filter:myfilter | orderBy:'age' | limitTo:2">
   {{ user }}
 </div>

Custom Filters

app.filter('charlimit', function() {
  return function(input,length) {
    if (!length) {
      length = 10
    }
    if (!input) {
      return ''
    }
    if (input.length <= length) {
      return input
    }
    else {
      return input.substring(0,length) + '...'
    }
  }
})

app.filter('candrink', function() {
  return function(data,minage) {
    var filtered = [];
    if (!minage) {
      minage = 21
    }
    for (var i=0;i<data.length;i++) {
      var value = data[i];
      if (value.age >= minage) {
        filtered.push(value);
      }
    }
    return filtered;
  }
})
<input ng-model="mydata.str">
{{ mydata.str | charlimit }}
<div ng-repeat="user in mydata.arr | candrink:mydata.str">
  {{ user }}
</div>

Service Types

Constants

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

app.controller('MainController', function($scope,constService) {
  console.log(constService)
})

app.constant('constService', {data: "this is returned data"})

Values

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

app.controller('MainController', function($scope,valService) {
  console.log(valService())
})

app.value('valService', function() {return "this is returned from a fn"})

Factories

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

app.controller('MainController', function($scope,myFactory) {
  console.log(myFactory.getdata())
})

app.factory('myFactory',function() {
  var mydata = "this is some other data"
  var myfunc = function() {}
  return {
    getdata: function() {
      return mydata
    }  
  }
})

Services

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

app.controller('MainController', function($scope,myService) {
  console.log(myService.getData())
  myService.addData('bla bla bla')
  console.log(myService.getData())
})

// app.service('myService',function() {
//   var myString = "this is some other data"
//   var addToString = function(newstr) {
//     myString += newstr
//   }
//
//   this.getData = function() {
//     return "String contains: " + myString
//   }
//   this.addData = addToString
// })

app.service('myService',ServiceClass)

function ServiceClass() {
  var myString = "this is some other data"
  var addToString = function(newstr) {
    myString += newstr
  }

  this.getData = function() {
    return "String contains: " + myString
  }
  this.addData = addToString
}

Providers

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

app.controller('MainController', function($scope,myTest) {
  console.log(myTest.getData())
  myTest.addData('bla bla bla')
  console.log(myTest.getData())
})

app.provider('myTest', function() {
  var myString = "this is some other data"
  var addToString = function(newstr) {
    myString += newstr
  }
  return {
    setData: function(data) {
      myString = data
    },
    $get: function() {
      return {
        getData: function() {
          return "String contains: " + myString
        },
        addData: addToString
      }
    }
  }
})

app.config(function(myTestProvider) {
  myTestProvider.setData('some different string')
})

Decorators

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

app.controller('MainController', function($scope,myFactory) {
  console.log(myFactory.getData())
  myFactory.reverse()
  console.log(myFactory.getData())
})

app.factory('myFactory',function() {
  var myString = "this is some other data"
  var addToString = function(newstr) {
    myString += newstr
  }
  return {
    getData: function() { return myString },
    setData: function(data) { myString = data },
    addData: addToString
  }
})

app.config(function($provide) {
  $provide.decorator('myFactory',function($delegate) {
    $delegate.reverse = function() {
      $delegate.setData($delegate.getData().split('').reverse().join(''))
    }
    return $delegate
  })
})

Dependency Injection Minification Issue

app.controller('MainController', function($scope, myFactory, myService) {
  // ...
})

With that in mind, Angular gives us a solution in the form of braces, so we can do the following:

app.controller('MainController', ['$scope', 'myFactory', 'myService', function(a,b,c) {
  // ...
}])

Directives

Possible applications

They should be defined as camel case, and applied as dash separated words.

 myDirective

 <my-directive></my-directive>
 <div my-directive></div>
 <div class="my-directive"></div>
 <!-- my-directive -->
<invetory-list item-detail pop-out is-selected="true" />

Info inside of a directive

app.directive('photo', function() {
  return {
    restrict: 'E', // E: Element, A: Attribute, C: Class, M: Comment
    template: '<figure>' +
                '<img width="500px" ng-src="{{photoSrc}}" />' +
                ' <figcaption>{{caption}}</figcaption>' +
              '</figure>',
    // // it can use an external HTML file:
    // templateUrl: 'photo.html',
    replace: true,
    // // only use link (more jquery-like) or scope (more angular-like)
    // link: function(scope, element, attrs) {
    //   attrs.$observe('caption', function(value){
    //     element.find('figcaption').text(value)
    //   })
    //   attrs.$observe('photoSrc', function(value){
    //     element.find('img').attr('src', value)
    //   })
    // }
    // // this is a controller inside the directive,
    // // so we can access parent controller scope data
    // controller: function($scope) {
    //   $scope.mydata = "some data"
    // }

    // // to display the original content of the html inside the directive
    // transclude: true,
    // template: '<div>content <div ng-transclude></div></div>',

    scope: {
      caption: '@',
      photoSrc: '@'
    }
  }
});
<photo photo-src="{{ photo.url }}" caption="Taken on: {{ photo.date }}" />

Variables variations in directives

 <input ng-model="val" />
 <input ng:model="val" />
 <input ng_model="val" />
 <input data-ng-model="val" /> <!-- this is the most HTML5-like variation -->
 <input x-ng-model="val" />

Routing

Basic routing

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

app.controller('MainController', function($scope) {
  $scope.somedata = "This is some data!!!"
});

app.config(function($routeProvider) {
  $routeProvider
    .when('/', {templateUrl: 'view.html', controller: 'MainController'});
})
<html ng-app="app">
  <body>
    <div ng-controller="MainController">
      <ng-view></ng-view>
    </div>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-route.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
    <script type="text/ng-template" id="view.html">
      <div>This is the view with some data here: {{ somedata }}</div>
    </script>
  </body>
</html>

A better way to declare the controller for the view, is in the view, not in the config declaration.

    .when('/', {templateUrl: 'view.html'});
    <div ng-controller="MainController">This is the view with some data here: {{ somedata }}</div>

More basic routing

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

app.controller('MainController', function($scope,$routeParams) {

  console.log($routeParams)
  $scope.somedata = $routeParams.myparam
});

app.config(function($routeProvider) {
  $routeProvider
    .when('/', {templateUrl: 'view.html'})
    .when('/test/:myparam/:myparam2/:myparam3', {templateUrl: 'view2.html'})
    .otherwise({template: 'Couldn\'t match a route'})
})
<html ng-app="app">
  <body>
    <div ng-controller="MainController">
      <ng-view></ng-view>
    </div>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-route.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
    <script type="text/ng-template" id="view.html">
      <div ng-controller="MainController">This is the view with some data here: {{ somedata }}</div>
    </script>
    <script type="text/ng-template" id="view2.html">
      <div ng-controller="MainController">This is the OTHER view with some data here: {{ somedata }}</div>
    </script>
  </body>
</html>
   .when('/test-search', {template: function(routeParams,path,search) {
      console.log(routeParams,path,search)
    }})

// URL: /test-search?parameter=20
// this is the 'search' parameter: search.parameter

Redirects

   .when('/test-redirect', {redirectTo: '/'})

Promises

app.controller('MainController', function($scope, $q, $timeout) {
  $scope.mydata = "Old data";
  
  var defer = $q.defer();
  
  defer.promise
    .then(functon(val) {
      $scope.mydata = val
    })

  $timeout(function() {
    defer.resolve("New data, baby!");
  }, 3000)
})

The then clause can be called again after a promise (sequential promises):

app.controller('MainController', function($scope, $q, $timeout) {
  $scope.mydata = "Old data";
  
  var defer = $q.defer();
  
  defer.promise
    .then(functon(val) {
      $scope.mydata += val
      return val
    })
    .then(functon(val) {
      $scope.mydata += val
      return val
    })
    .then(functon(val) {
      $scope.mydata += val
      return val
    })

  $timeout(function() {
    defer.resolve("New data, baby! ");
  }, 3000)
})

Resolve

This is not neccesary because the angularjs' data binding makes this not really useful, but it can become handy to have it available. This will not render/display the template, unless the promise is resolved.

    .when('/',
      {
        templateUrl: 'view.html',
        resolve: {
          data1: function($q,$timeout) {
            var defer = $q.defer();
            $timeout(function() {
              defer.resolve();
              console.log('finished')
            }, 2000);
            return defer.promise;
          }
        }
      })

Routing Events

app.controller('MainController', function($scope, $rootScope, $route, $location) {
  $scope.somedata = "This is some data!"

  $scope.navigate = function() {
    console.log($scope);
    $location.path('/newroute');
  }

  $rootScope.$on("$routeChangeStart", function(event, current, previous, rejection) {
    // after the route change
    console.log("Route Change Start!");
    console.log(event, current, previous, rejection);
  })

  $rootScope.$on("$routeChangeSuccess", function(event, current, previous, rejection) {
    // before the route change
    console.log("Route Change Success!");
    console.log(event, current, previous, rejection);
  })
})

Organizing AngularJS Modules

This module organization by categories is made so the app can scale less messy.

'use strict';

angular.module('myApp', ['myApp.groups', 'myApp.users']);

angular.module('myApp.groups', ['myApp.groups.controllers', 'myApp.groups.directives']);

angular.module('myApp.users', ['myApp.users.controllers', 'myApp.users.directives']);

Interacting With Servers

$http

app.controller('MainController', function($scope, $http) {
  $scope.getFromAPI = function() {
    $http({method: 'GET', url: 'http://location.com/'})
      .success(function(data, status, headers, config){
        console.log('success', status);
        console.log(data)
      })
      .error(function(data, status, headers, config){
        console.log('error!', status);
        console.log(data)
      });
  }
});
// methods: 'GET', 'POST', 'PUT', 'DELETE', 'JSON', 'JSONP'

Shorter version:

$http.get('http://location.com/')
  .success()
  .error();

$http.post('http://location.com/', data)
  .success()
  .error();

$resource

We have to add the angular-resource.min.js file to make $resource calls.

 <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-route.min.js"></script>
var app = angular.module('app', ['app.angularGit']);

angular.controller("MainController", function($scope, AngularGit) {
  // the params are not important to the API
  // it's important so they match the URL paramters that $resource is using
  var params = {data: 'info', user: 'UserName'};
  
  console.log(AngularGit.get(params));
});

angular.module('app.angularGit', ['ngResource'])
  .factory('AngularGit', function($resource) {
    return $resource('http://location.com/api/users/:data/:user')
  });

$resource default methods:

{
  'get': {method:'GET'},
  'save': {method:'POST'},
  'query': {method:'GET', isArray:true},
  'remove': {method:'DELETE'},
  'delete': {method:'DELETE'}
}

We can also add custom methods, so we can customize our communication with the server:

// this code is taken out from StackOverflow
app.factory('User', function ($resource) {
    return $resource(
        '/api/user/:listCtrl:id/:docCtrl/', {
            id: '@id',
            listCtrl: '@listCtrl',
            docCtrl: '@docCtrl'
        }, {
            update: {
                method: 'PUT'
            },
            current: {
                method: 'GET',
                params: {
                    listCtrl: 'current'
                }
            },
            nearby: {
                method: 'GET',
                params: {
                    docCtrl: 'nearby'
                },
                isArray: true
            }
        }
    );
});

AngularJS tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment