the art of angularjs in 2015
TRANSCRIPT
![Page 2: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/2.jpg)
© 2014 Raible Designs
Blogger on raibledesigns.com
Founder of AppFuse
Father, Skier, Mountain Biker, Whitewater Rafter
Web Framework Connoisseur
Who is Matt Raible?
Bus Lover
![Page 3: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/3.jpg)
© 2015 Raible Designs
Devoxx4Kids Denver• Teaching Kids to Program
• Java, Minecraft, robots, oh my!
• Non profit, looking for donations and speakers
http://www.meetup.com/Devoxx4Kids-Denver/
![Page 4: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/4.jpg)
© 2015 Raible Designs
How to Become an ArtistPart 1 of 3: Learn the Basics on Your Own
Take some time and try various mediums of artRecognize your strengthsDo your research and learn the basicsGet the supplies you will needObserve the world around youMake time for your art every daySeek out the opinions of othersDevelop your own style http://www.wikihow.com/Become-an-Artist
![Page 5: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/5.jpg)
© 2015 Raible Designs
Jobs on Dice.comJanuary 2015
0
225
450
675
900
Back
bone
Angu
lar
Embe
r
Knoc
kout
Reac
t
![Page 6: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/6.jpg)
© 2015 Raible Designs
LinkedIn SkillsJanuary 2015
0
25,000
50,000
75,000
100,000
Back
bone
Angu
lar
Knoc
kout
Embe
r
Reac
t
![Page 7: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/7.jpg)
© 2015 Raible Designs
Google Trends
![Page 8: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/8.jpg)
© 2015 Raible Designs
Indeed Job Trends
Absolute
Relative
![Page 9: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/9.jpg)
© 2015 Raible Designs
Stack Overflow
![Page 10: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/10.jpg)
![Page 11: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/11.jpg)
© 2015 Raible Designs
Who wants to learn ?
![Page 12: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/12.jpg)
© 2015 Raible Designs
The History of AngularJSStarted 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
![Page 13: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/13.jpg)
© 2015 Raible Designs
The History of AngularJS
0
4500
9000
13500
18000
Lines of Code
17,000
1,000
AngularJS GWT
![Page 14: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/14.jpg)
© 2015 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.3.11/angular.min.js"></script> </body> </html>
![Page 15: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/15.jpg)
© 2015 Raible Designs
Architecture Principles
Structure
Testability
Boilerplate
D.R.Y.
![Page 16: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/16.jpg)
© 2015 Raible Designs
Code Organization
Start with Angular Seed*
* more options to be discussed later…
git clone https://github.com/angular/angular-seed.git
![Page 17: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/17.jpg)
© 2015 Raible Designs
Quick Demo
![Page 18: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/18.jpg)
© 2015 Raible Designs
App Definition
var app = angular.module('myApp', []);
<!DOCTYPE html> <html ng-app="myApp">
![Page 19: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/19.jpg)
© 2015 Raible Designs
App Definition with separate filesapp.js
controllers.js
angular.module('myApp', ['ngRoute', 'myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers' ])
angular.module('myApp.controllers', []). controller('MyCtrl1', [function() {
}])
![Page 20: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/20.jpg)
© 2015 Raible Designs
Model View Controller
![Page 21: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/21.jpg)
© 2015 Raible Designs
Data Bindingfriend.js
friend.html
$scope.friend = { name: "Fernand" };
{{friend.name}} // 1-way <input ng-model="friend.name"> // 2-way
![Page 22: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/22.jpg)
© 2015 Raible Designs
Solving FOUCThis will work just fine — if it’s not on the first page:
Use ng-cloak or ng-bind attribute:
<p>{{friend.name}}</p>
<p ng-cloak>{{friend.name}}</p>
<p ng-bind="friend.name"></p>
![Page 23: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/23.jpg)
© 2015 Raible Designs
Directives
<div ng-repeat="entry in news.entries"> <span ng-bind="entry.title"></span> <button ng-click="delete($index)"> Delete </button> </div>
![Page 24: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/24.jpg)
© 2015 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>
![Page 25: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/25.jpg)
© 2015 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}}' }; });
![Page 26: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/26.jpg)
© 2015 Raible Designs
Built-In Directivesng-href
ng-src
ng-disabled
ng-checked
ng-readonly
ng-selected
ng-class
ng-style
![Page 27: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/27.jpg)
© 2015 Raible Designs
Servicesvar 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'}); });
![Page 28: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/28.jpg)
© 2015 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);
![Page 29: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/29.jpg)
© 2015 Raible Designs
$qmyApp.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 }; });
![Page 30: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/30.jpg)
© 2015 Raible Designs
$q
myApp.controller('HelloCtrl', function($scope, HelloWorld) {
HelloWorld.getMessages().then(function(messages) { $scope.messages = messages; });
});
![Page 31: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/31.jpg)
© 2015 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("/"); });
}; })
![Page 32: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/32.jpg)
© 2015 Raible Designs
Filters
also: lowercase, limitTo, orderBy
{{ 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' }}
![Page 33: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/33.jpg)
© 2015 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('!'); }] )
![Page 34: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/34.jpg)
© 2015 Raible Designs
Routing: Navigation
$rootScope.logout = function () { delete $rootScope.user; delete $http.defaults.headers.common[xAuthTokenHeaderName]; $cookieStore.remove('user'); $location.path("/login"); };
![Page 35: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/35.jpg)
© 2015 Raible Designs
Routing: Navigation
$rootScope.logout = function () { delete $rootScope.user; delete $http.defaults.headers.common[xAuthTokenHeaderName]; $cookieStore.remove('user'); $location.path("/login"); };
![Page 36: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/36.jpg)
© 2015 Raible Designs
Code Organization RevisitedLineman 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
![Page 37: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/37.jpg)
![Page 38: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/38.jpg)
![Page 39: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/39.jpg)
Google's Recommendations for Angular App Structure
![Page 40: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/40.jpg)
![Page 41: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/41.jpg)
© 2015 Raible Designs
TestingKarma - test runner, framework agnostic
Jasmine - unit tests, framework agnostic
Protractor - integration tests, angular specific
Lineman - productivity, framework agnostic
![Page 42: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/42.jpg)
© 2015 Raible Designs
Testing: Controllersdescribe("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 }); }));
![Page 43: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/43.jpg)
© 2015 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'); }); }); });
![Page 44: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/44.jpg)
© 2015 Raible Designs
Testing: DirectivesbeforeEach(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); }); });
![Page 45: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/45.jpg)
© 2015 Raible Designs
Testing: Directives with CoffeeScriptdescribe "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
![Page 46: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/46.jpg)
© 2015 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"
![Page 47: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/47.jpg)
© 2015 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"
![Page 48: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/48.jpg)
© 2015 Raible Designs
Gruntfile.jsmodule.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}'] } },
![Page 49: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/49.jpg)
© 2015 Raible Designs
Gruntfile.js useminPrepare: { html: 'app/index.html' },
usemin: { html: ['dist/index.html'] },
uglify: { options: { report: 'min', mangle: false } } });
![Page 50: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/50.jpg)
© 2015 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' ]); };
![Page 51: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/51.jpg)
© 2015 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>
![Page 52: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/52.jpg)
© 2015 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>
![Page 53: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/53.jpg)
© 2015 Raible Designs
After Grunt
http://raibledesigns.com/rd/entry/using_grunt_with_angularjs_for
![Page 54: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/54.jpg)
© 2015 Raible Designs
You shouldn’t have to worry about FEO
http://raibledesigns.com/rd/entry/you_shouldn_t_have_to
![Page 55: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/55.jpg)
© 2015 Raible Designs
HTTP/2 Performance Anti-Patterns?Split dominant content domains
Reduce requests
Merging
Sprites
DataURIshttp://www.slideshare.net/andydavies
![Page 56: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/56.jpg)
© 2015 Raible Designs
UI Bootstrap http://angular-ui.github.io/bootstrap
<script src="lib/angular/ui-bootstrap-0.12.0.min.js"></script> <script src="lib/angular/ui-bootstrap-tpls-0.12.0.min.js"></script>
angular.module('myApp', ['ui.bootstrap']);
![Page 57: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/57.jpg)
© 2015 Raible Designs
UI Bootstrap: Carousel
![Page 58: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/58.jpg)
© 2015 Raible Designs
UI Bootstrap: Carousel
<div ng-controller="CarouselDemoCtrl"> <div style="height: 305px"> <carousel interval="myInterval"> <slide ng-repeat="slide in slides" active="slide.active"> <img ng-src="{{slide.image}}" style="margin:auto;"> <div class="carousel-caption"> <h4>Slide {{$index}}</h4> <p>{{slide.text}}</p> </div> </slide> </carousel> </div> </div>
![Page 59: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/59.jpg)
© 2015 Raible Designs
Foundation for Apps http://foundation.zurb.com/apps
![Page 60: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/60.jpg)
© 2015 Raible Designs
Foundation
![Page 61: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/61.jpg)
© 2015 Raible Designs
Foundation
![Page 62: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/62.jpg)
© 2015 Raible Designs
Sass Mixins
<div class="row"> <main class="medium-9 columns"> <p>Main content</p> </main> <aside class="medium-3 columns"> <p>Sidebar</p> </aside> </div>
![Page 63: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/63.jpg)
© 2015 Raible Designs
Sass Mixins
<div class="layout"> <main class="layout-content"> <p>Main content</p> </main> <aside class="layout-sidebar"> <p>Sidebar</p> </aside> </div>
![Page 64: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/64.jpg)
© 2015 Raible Designs
Sass Mixins
http://bit.ly/1Kh1ha5
@import "foundation/components/grid"; .layout { // `layout` container functions as a row @include grid-row(); } .layout-content { // Mobile-first: make `layout-container` full-width @include grid-column(12); // On medium-up size, make `layout-container` 9 columns wide @media #{$medium-up} { @include grid-column(9); } } .layout-sidebar { // Mobile-first: make `layout-sidebar` full-width @include grid-column(12); // On medium-up size, make `layout-sidebar` 3 columns wide @media #{$medium-up} { @include grid-column(3); } }
![Page 66: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/66.jpg)
© 2015 Raible Designs#dv13javaweb$
My Ionic Experience
http://raibledesigns.com/rd/entry/developing_an_ios_native_app
![Page 67: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/67.jpg)
© 2015 Raible Designs
JHipster http://jhipster.github.io/
![Page 68: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/68.jpg)
© 2015 Raible Designs
JHipster
Spring Boot
Spring Security
AngularJS
Bootstrap
Bower
Metrics
Java 7 or Java 8
Maven or Gradle
Authentication Type: cookie-based or OAuth2
Type of Database: SQL or NoSQL
Caching: EhCache or Hazelcast
Grunt or Gulp.js
http://jhipster.github.io/
Foundational Frameworks Project Options
![Page 69: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/69.jpg)
© 2015 Raible Designs
JHipster
![Page 70: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/70.jpg)
© 2015 Raible Designs
JHipster: Metrics
![Page 71: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/71.jpg)
© 2015 Raible Designs
JHipster: Code Generation
![Page 72: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/72.jpg)
© 2015 Raible Designs
JHipster: Code Generation
![Page 73: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/73.jpg)
© 2015 Raible Designs
AngularJS Batarang
![Page 74: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/74.jpg)
© 2015 Raible Designs
My Experience in 2013Developing with AngularJS Series
Part I: The BasicsPart II: Dialogs and Data Part III: ServicesPart IV: Making it Pop
![Page 75: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/75.jpg)
© 2015 Raible Designs#dv13javaweb$
My Experience in 2013
http://vimeo.com/mraible/angularjs-deep-dive
![Page 76: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/76.jpg)
© 2015 Raible Designs
2015 AngularJS TutorialsGetting Started with AngularJS
http://raibledesigns.com/rd/entry/getting_started_with_angularjs
Testing AngularJS Applications
http://raibledesigns.com/rd/entry/testing_angularjs_applications
![Page 77: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/77.jpg)
© 2015 Raible Designs
Spring and AngularJS http://spring.io/blog
http://spring.io/blog/2015/01/12/spring-and-angular-js-a-secure-single-page-application
![Page 78: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/78.jpg)
© 2015 Raible Designs
Angular 2.0
<input type="text" [value]="firstName">
<button (click)="addPerson()">Add</button>
<input type="checkbox" [checked]="someProperty">
![Page 79: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/79.jpg)
© 2015 Raible Designs
Concepts Eliminated in 2.0Controllers
Directive Definition Object
$scope
angular.module
jqLite
![Page 80: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/80.jpg)
© 2015 Raible Designs
The Bad NewsNo migration path from Angular 1.x to 2.0
Angular 1.3 will be supported for 1.5 - 2 years
Will only support Evergreen Browsers (e.g. IE10+)
Learn more on
http://www.infoq.com/news/2014/10/angular-2-atscript
![Page 82: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/82.jpg)
© 2015 Raible Designs
How to Become an ArtistPart 1 of 3: Learn the Basics on Your Own
Take some time and try various mediums of artRecognize your strengthsDo your research and learn the basicsGet the supplies you will needObserve the world around youMake time for your art every daySeek out the opinions of othersDevelop your own style http://www.wikihow.com/Become-an-Artist
![Page 83: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/83.jpg)
© 2015 Raible Designs
Shortcut to becoming an Angular Artist
JUST DO IT.
![Page 84: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/84.jpg)
© 2015 Raible Designs
Contact Me!http://raibledesigns.com
@mraible
Presentationshttp://slideshare.net/mraible
Codehttp://github.com/mraible
Questions?
![Page 85: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/85.jpg)
© 2015 Raible Designs
Who to follow on Twitter
AngularJS Team at Google
Miško Hevery - @mhevery
Igor Minar - @IgorMinar
Brian Ford - @briantford
Web Performance
Ilya Grigorik - @igrigorik
Andy Davis - @andydavies
Steve Souders - @Souders
![Page 86: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/86.jpg)
© 2015 Raible Designs
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/
Resources
![Page 87: The Art of AngularJS in 2015](https://reader034.vdocument.in/reader034/viewer/2022042615/55a525741a28abea0e8b467e/html5/thumbnails/87.jpg)
© 2015 Raible Designs
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
Code