• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
The Art of AngularJS
 

The Art of AngularJS

on

  • 43,009 views

AngularJS is one of today's hottest JavaScript MVC Frameworks. In this session, we'll explore many concepts it brings to the world of client-side development: dependency injection, directives, ...

AngularJS is one of today's hottest JavaScript MVC Frameworks. In this session, we'll explore many concepts it brings to the world of client-side development: dependency injection, directives, filters, routing and two-way data binding. We'll also look at its recommended testing tools and build systems. Finally, you'll learn about my experience developing several real-world applications using AngularJS, HTML5 and Bootstrap.

Statistics

Views

Total Views
43,009
Views on SlideShare
9,702
Embed Views
33,307

Actions

Likes
77
Downloads
1,293
Comments
0

90 Embeds 33,307

http://mobicon.tistory.com 13203
http://raibledesigns.com 10304
http://java.dzone.com 6960
https://raibledesigns.com 706
http://server.dzone.com 655
http://feedly.com 471
http://www.raibledesigns.com 310
http://www.ivanteoh.com 94
https://twitter.com 80
http://localhost 64
http://raible18.rssing.com 54
http://www.oyous.com 52
http://plus.url.google.com 26
http://www.google.co.kr 24
http://raible.kgbinternet.com 22
http://www.newsblur.com 20
http://cafe.naver.com 16
http://reader.nunux.org 15
https://bazqux.com 14
http://newsblur.com 14
http://css.dzone.com 13
http://daenamu84.tistory.com 13
http://127.0.0.1 11
http://architects.dzone.com 10
http://experiments.interactive-1.studionorth.net 10
http://webcache.googleusercontent.com 9
http://nodeweb.cafe24app.com 9
http://www.feedspot.com 9
http://reader.aol.com 7
http://smashingreader.com 6
http://feedreader.com 6
http://keeper.nunux.org 5
http://www.dzone.com 5
https://www.linkedin.com 5
http://inoreader.com 5
https://raible.kgbinternet.com 4
http://news.google.com 4
http://www.inoreader.com 3
http://translate.googleusercontent.com 3
http://www.linkedin.com 3
https://reader.aol.com 3
http://rritw.com 3
https://www.google.com.au 2
https://inoreader.com 2
http://www.google.fr 2
http://digg.com 2
http://www.google.it 2
https://www.inoreader.com 2
http://silverreader.com 2
http://www.google.de 2
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    The Art of AngularJS The Art of AngularJS Presentation Transcript

    • The Art of Matt Raible • http://raibledesigns.com Photos by
    • Modern Principles in Web Development Design for mobile first (even if you’re not building a mobile app) Build only single page apps Create and use your own REST API “Sex sells” applies to web apps © 2014 Raible Designs
    • Jobs on Dice.com February 2014 500 375 250 125 © 2014 Raible Designs ut ko oc Kn be r Em lar gu An Ba ck bo n e 0
    • LinkedIn Skills February 2014 30,000 22,500 15,000 7,500 © 2014 Raible Designs be r Em ut ko oc Kn lar gu An Ba ck bo n e 0
    • Google Trends © 2014 Raible Designs
    • Indeed Job Trends Absolute Relative © 2014 Raible Designs
    • Stack Overflow © 2014 Raible Designs
    • Who wants to learn © 2014 Raible Designs ?
    • The History of AngularJS Started by Miško Hevery in 2009 GWT = 3 developers, 6 months AngularJS = 1 developer, 3 weeks Learn more: https://www.youtube.com/watch?v=X0VsStcCCM8 © 2014 Raible Designs
    • The History of AngularJS AngularJS GWT 18000 17,000 13500 9000 4500 0 1,000 Lines of Code © 2014 Raible Designs
    • Hello World <!doctype html> <html ng-app> <head> <title>Hello World</title> </head> <body> <div> <label>Name:</label> <input type="text" ng-model="name" placeholder="Enter a name here"> <hr> <h1>Hello {{name}}!</h1> </div> <script src="http://code.angularjs.org/1.2.13/angular.min.js"></script> </body> </html> © 2014 Raible Designs
    • Architecture Principles Boilerplate Structure D.R.Y. Testability © 2014 Raible Designs
    • Code Organization Start with Angular Seed* ! git clone https://github.com/angular/angular-seed.git ! ! ! * more options to be discussed later… © 2014 Raible Designs
    • App Definition var app = angular.module('myApp', []); <!DOCTYPE html> <html ng-app="myApp"> © 2014 Raible Designs
    • App Definition with separate files app.js ! ! angular.module('myApp', ['ngRoute', 'myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers' ]) controllers.js angular.module('myApp.controllers', []). controller('MyCtrl1', [function() { ! }]) © 2014 Raible Designs
    • Model View Controller © 2014 Raible Designs
    • Data Binding friend.js ! $scope.friend = { name: "Fernand" }; ! friend.html {{friend.name}} // 1-way <input ng-model="friend.name"> // 2-way © 2014 Raible Designs
    • Solving FOUC This will work just fine — if it’s not on the first page: ! <p>{{friend.name}}</p> Use ng-cloak or ng-bind attribute: <p ng-cloak>{{friend.name}}</p> ! <p ng-bind="friend.name"></p> © 2014 Raible Designs
    • Directives <div ng-repeat="entry in news.entries"> <span ng-bind="entry.title"></span> <button ng-click="delete($index)"> Delete </button> </div> © 2014 Raible Designs
    • Directives with valid HTML5 <div data-ng-repeat="entry in news.entries"> <span data-ng-bind="entry.title"></span> <button data-ng-click="delete($index)"> Delete </button> </div> <div data-ng:repeat="entry in news.entries"> <span data-ng:bind="entry.title"></span> <button data-ng:click="delete($index)"> Delete </button> </div> © 2014 Raible Designs
    • Custom Directives $scope.customer = { name: 'Franklin', address: '1830 Blake' }; <div ng-controller="MyController"> <my-customer></my-customer> </div> .directive('myCustomer', function() { return { template: 'Name: {{customer.name}} Address: {{customer.address}}' }; }); © 2014 Raible Designs
    • Built-In Directives ng-href ng-selected ng-src ng-class ng-disabled ng-style ng-checked ! ng-readonly © 2014 Raible Designs
    • Services var services = angular.module('myApp.services', ['ngResource']); ! services.factory('LoginService', function($resource) { return $resource(':action', {}, { authenticate: { method: 'POST', params: {'action': 'authenticate'}, headers: {'Content-Type': 'application/x-www-form-urlencoded'} } } ); }); ! services.factory('NewsService', function($resource) { return $resource('news/:id', {id: '@id'}); }); © 2014 Raible Designs
    • $http $http({method: 'GET', url: '/news'}). success(function(data, status, headers, config) { // this callback will be called asynchronously // when the response is available }). error(function(data, status, headers, config) { // called asynchronously if an error occurs // or server returns response with an error status. }); $http.get('/news').success(successCallback); $http.post('/news', data).success(successCallback); © 2014 Raible Designs
    • $q myApp.factory('HelloWorld', function($q, $timeout) { ! var getMessages = function() { var deferred = $q.defer(); ! $timeout(function() { deferred.resolve(['Hello', 'world!']); }, 2000); ! return deferred.promise; }; ! return { getMessages: getMessages }; }); © 2014 Raible Designs
    • $q myApp.controller('HelloCtrl', function($scope, HelloWorld) { ! HelloWorld.getMessages().then(function(messages) { $scope.messages = messages; }); ! }); © 2014 Raible Designs
    • Dependency Injection .controller('LoginController', function($scope, $rootScope, $location, $http, $cookieStore, LoginService) { $scope.login = function () { LoginService.authenticate($.param({username: $scope.username, 
 password: $scope.password}), function (user) { $rootScope.user = user; $http.defaults.headers.common[xAuthTokenHeaderName] = user.token; $cookieStore.put('user', user); $location.path("/"); }); }; }) © 2014 Raible Designs
    • Filters ! ! ! ! {{ name | uppercase }} ! <!-- Displays: 123.46 --> {{ 123.456789 | number:2 }} ! <!-- In en-US locale, '$1000.00' will be shown --> {{ 1000 | currency }} ! <!-- all of the words with e in them ["Lerner","Likes","Eat"] --> {{ ['Ari', 'Lerner', 'Likes', 'To', 'Eat', 'Pizza'] | filter:'e' }} ! also: lowercase, limitTo, orderBy © 2014 Raible Designs
    • Routes .config(['$routeProvider', '$locationProvider', '$httpProvider', function ($routeProvider, $locationProvider, $httpProvider) { $routeProvider.when('/create', { templateUrl: 'partials/create.html', controller: 'CreateController' }); $routeProvider.when('/edit/:id', { templateUrl: 'partials/edit.html', controller: 'EditController' }); $routeProvider.when('/login', { templateUrl: 'partials/login.html', controller: 'LoginController' }); $routeProvider.otherwise({ templateUrl: 'partials/index.html', controller: 'IndexController' }); ! $locationProvider.hashPrefix('!'); }] ) © 2014 Raible Designs
    • Routing: Navigation $rootScope.logout = function () { delete $rootScope.user; delete $http.defaults.headers.common[xAuthTokenHeaderName]; $cookieStore.remove('user'); $location.path("/login"); }; © 2014 Raible Designs
    • Routing: Navigation $rootScope.logout = function () { delete $rootScope.user; delete $http.defaults.headers.common[xAuthTokenHeaderName]; $cookieStore.remove('user'); $location.path("/login"); }; © 2014 Raible Designs
    • Code Organization Revisited Lineman helps you build fat-client JavaScript apps It produces happiness by building assets, mocking servers, and running specs on every file change git clone https://github.com/linemanjs/lineman-angular-template.git my-app cd my-app sudo npm install -g lineman npm install lineman run © 2014 Raible Designs
    • Google's Recommendations for Angular App Structure
    • Testing Testem - test runner, framework agnostic Jasmine - unit tests, framework agnostic Protractor - integration tests, angular specific Lineman - productivity, framework agnostic © 2014 Raible Designs
    • Testing: Controllers describe("controller: LoginController", function() { ! beforeEach(function() { module("app"); }); ! beforeEach(inject(function($controller, $rootScope, $location, AuthenticationService, $httpBackend) { this.$location = $location; this.$httpBackend = $httpBackend; this.scope = $rootScope.$new(); this.redirect = spyOn($location, 'path'); $controller('LoginController', { $scope: this.scope, $location: $location, AuthenticationService: AuthenticationService }); })); © 2014 Raible Designs
    • Testing: Controllers afterEach(function() { this.$httpBackend.verifyNoOutstandingRequest(); this.$httpBackend.verifyNoOutstandingExpectation(); }); ! describe("successfully logging in", function() { it("should redirect you to /home", function() { this.$httpBackend.expectPOST('/login', this.scope.credentials).respond(200); this.scope.login(); this.$httpBackend.flush(); expect(this.redirect).toHaveBeenCalledWith('/home'); }); }); }); © 2014 Raible Designs
    • Testing: Directives beforeEach(inject(function($rootScope, $compile) { this.directiveMessage = 'ralph was here'; this.html = "<div shows-message-when-hovered message='" + this.directiveMessage + "'></div>"; this.scope = $rootScope.$new(); this.scope.message = this.originalMessage = 'things are looking grim'; this.elem = $compile(this.html)(this.scope); })); ! describe("when a user mouses over the element", function() { it("sets the message on the scope to the message attribute", function() { this.elem.triggerHandler('mouseenter'); expect(this.scope.message).toBe(this.directiveMessage); }); }); © 2014 Raible Designs
    • Testing: Directives with CoffeeScript describe "directive: shows-message-when-hovered (coffeescript)", -> ! Given -> module("app") ! Given inject ($rootScope, $compile) -> @directiveMessage = 'ralph was here' @html = "<div shows-message-when-hovered message='#{@directiveMessage}'></div>" @scope = $rootScope.$new() @scope.message = @originalMessage = 'things are looking grim' @elem = $compile(@html)(@scope) ! describe "when a user mouses over the element", -> When -> @elem.triggerHandler('mouseenter') Then "the message on the scope is set to the message attribute", -> @scope.message == @directiveMessage © 2014 Raible Designs
    • Testing: End-to-End protractor = require("protractor") require "protractor/jasminewd" require 'jasmine-given' ! describe "my angular app", -> ptor = protractor.getInstance() describe "visiting the login page", -> Given -> ptor.get "/" ! describe "when a user logs in", -> Given -> ptor.findElement(protractor.By.input("credentials.username")).sendKeys "Ralph" Given -> ptor.findElement(protractor.By.input("credentials.password")).sendKeys "Wiggum" When -> ptor.findElement(protractor.By.id("log-in")).click() Then -> ptor.findElement(protractor.By.binding("{{ message }}")).getText().then (text) -> expect(text).toEqual "Mouse Over these images to see a directive at work" © 2014 Raible Designs
    • Building with Grunt sudo npm install ! sudo npm install -g grunt-cli ! vi package.json ! "grunt": "~0.4.1", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-uglify": "~0.2.7", "grunt-contrib-cssmin": "~0.7.0", "grunt-usemin": "~2.0.2", "grunt-contrib-copy": "~0.5.0", "grunt-rev": "~0.1.0", "grunt-contrib-clean": "~0.5.0", "matchdep": "~0.3.0" © 2014 Raible Designs
    • Gruntfile.js module.exports = function (grunt) { ! ! ! ! grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), clean: ["dist", '.tmp'], copy: { main: { expand: true, cwd: 'app/', src: ['**', '!js/**', '!lib/**', '!**/*.css'], dest: 'dist/' } }, rev: { files: { src: ['dist/**/*.{js,css}'] } }, © 2014 Raible Designs
    • Gruntfile.js ! useminPrepare: { html: 'app/index.html' }, ! usemin: { html: ['dist/index.html'] }, ! uglify: { options: { report: 'min', mangle: false } } }); ! © 2014 Raible Designs
    • Gruntfile.js require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); ! // Tell Grunt what to do when we type "grunt" into the terminal grunt.registerTask('default', [ 'copy', 'useminPrepare', 'concat', 'uglify', 'cssmin', 'rev', 'usemin' ]); }; © 2014 Raible Designs
    • index.html comments <head> <title>My AngularJS App</title> <!-- build:css css/seed.min.css --> <link rel="stylesheet" href="css/app.css"/> <link rel="stylesheet" href="css/app2.css"/> <!-- endbuild --> </head> <body> <!-- build:js js/seed.min.js --> <script src="lib/angular/angular.js"></script> <script src="lib/angular/angular-route.js"></script> <script src="js/app.js"></script> <script src="js/services.js"></script> <script src="js/controllers.js"></script> <script src="js/filters.js"></script> <script src="js/directives.js"></script> <!-- endbuild --> </body> © 2014 Raible Designs
    • dist/index.html <head> <title>My AngularJS App</title> <link rel="stylesheet" href="css/f050d0dc.seed.min.css"/> </head> <body> ! <script src="js/8973cf0f.seed.min.js"></script> </body> © 2014 Raible Designs
    • After Grunt http://raibledesigns.com/rd/entry/using_grunt_with_angularjs_for © 2014 Raible Designs
    • You shouldn’t have to worry about FEO http://raibledesigns.com/rd/entry/you_shouldn_t_have_to © 2014 Raible Designs
    • HTTP/2 Performance Anti-Patterns? Split dominant content domains Reduce requests Merging Sprites DataURIs http://www.slideshare.net/andydavies © 2014 Raible Designs
    • CloudBees © 2014 Raible Designs
    • UI Bootstrap http://angular-ui.github.io/bootstrap <script src="lib/angular/ui-bootstrap-0.10.0.min.js"></script> <script src="lib/angular/ui-bootstrap-tpls-0.10.0.min.js"></script> angular.module('myApp', ['ui.bootstrap']); © 2014 Raible Designs
    • Ionic Framework http://ionicframework.com © 2014 Raible Designs
    • AngularJS Batarang © 2014 Raible Designs
    • My Experience Developing with AngularJS Series Part I: The Basics
 Part II: Dialogs and Data
 Part III: Services
 Part IV: Making it Pop
 © 2014 Raible Designs
    • My Experience http://vimeo.com/mraible/angularjs-deep-dive #dv13javaweb$ © 2014 Raible Designs
    • How to Become an Artist Part 1 of 3: Learn the Basics on Your Own Take some time and try various mediums of art Recognize your strengths Do your research and learn the basics Get the supplies you will need Observe the world around you Make time for your art every day Seek out the opinions of others Develop your own style http://www.wikihow.com/Become-an-Artist © 2014 Raible Designs
    • Shortcut to becoming an Angular Artist JUST DO IT. © 2014 Raible Designs
    • Questions? Contact Me! http://raibledesigns.com @mraible Presentations http://slideshare.net/mraible Code http://github.com/mraible © 2014 Raible Designs
    • Who to follow on Twitter AngularJS Team at Google Web Performance Miško Hevery - @mhevery Ilya Grigorik - @igrigorik Igor Minar - @IgorMinar Andy Davis - @andydavies Brian Ford - @briantford Steve Souders - @Souders ! © 2014 Raible Designs
    • Resources Angular Dart https://angulardart.org Devoxx AngularJS Talks on Parleys.com http://parleys.com/play/5148922b0364bc17fc56c91b (2012) http://parleys.com/play/529321a5e4b054cd7d2ef4e1 (2013) Egghead.io - https://egghead.io/ © 2014 Raible Designs
    • Code Angular Seed https://github.com/angular/angular-seed Lineman Application Template using AngularJS https://github.com/linemanjs/lineman-angular-template AngularJS + Rest + Spring Security https://github.com/joshlong/boot-examples/tree/master/x-auth-security © 2014 Raible Designs