SlideShare a Scribd company logo
Photos by

The Art of in 2015
Matt Raible • http://raibledesigns.com
© 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
© 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/
© 2015 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
© 2015 Raible Designs
Jobs on Dice.com
January 2015
0
225
450
675
900
Backbone
Angular
Em
ber
Knockout
React
© 2015 Raible Designs
LinkedIn Skills
January 2015
0
25,000
50,000
75,000
100,000
Backbone
Angular
Knockout
Em
ber
React
© 2015 Raible Designs
Google Trends
© 2015 Raible Designs
Indeed Job Trends
Absolute
Relative
© 2015 Raible Designs
Stack Overflow
The Art of AngularJS in 2015
© 2015 Raible Designs
Who wants to learn ?
© 2015 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
© 2015 Raible Designs
The History of AngularJS
0
4500
9000
13500
18000
Lines of Code
17,000
1,000
AngularJS GWT
© 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>
© 2015 Raible Designs
Architecture Principles
Structure
Testability
Boilerplate
D.R.Y.
© 2015 Raible Designs
Code Organization
Start with Angular Seed*

* more options to be discussed later…
git clone https://github.com/angular/angular-seed.git
© 2015 Raible Designs
Quick Demo
© 2015 Raible Designs
App Definition
var app = angular.module('myApp', []);
<!DOCTYPE html>
<html ng-app="myApp">
© 2015 Raible Designs
App Definition with separate files
app.js

controllers.js
angular.module('myApp', ['ngRoute',
'myApp.filters',
'myApp.services',
'myApp.directives',
'myApp.controllers'
])
angular.module('myApp.controllers', []).
controller('MyCtrl1', [function() {
}])
© 2015 Raible Designs
Model View Controller
© 2015 Raible Designs
Data Binding
friend.js

friend.html

$scope.friend = {
name: "Fernand"
};
{{friend.name}} // 1-way
<input ng-model="friend.name"> // 2-way
© 2015 Raible Designs
Solving FOUC
This 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>
© 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>
© 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>
© 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}}'
};
});
© 2015 Raible Designs
Built-In Directives
ng-href

ng-src

ng-disabled

ng-checked

ng-readonly

ng-selected

ng-class

ng-style
© 2015 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'});
});
© 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);
© 2015 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
};
});
© 2015 Raible Designs
$q
myApp.controller('HelloCtrl', function($scope, HelloWorld) {
HelloWorld.getMessages().then(function(messages) {
$scope.messages = messages;
});
});
© 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("/");
});
};
})
© 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' }}
© 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('!');
}]
)
© 2015 Raible Designs
Routing: Navigation
$rootScope.logout = function () {
delete $rootScope.user;
delete $http.defaults.headers.common[xAuthTokenHeaderName];
$cookieStore.remove('user');
$location.path("/login");
};
© 2015 Raible Designs
Routing: Navigation
$rootScope.logout = function () {
delete $rootScope.user;
delete $http.defaults.headers.common[xAuthTokenHeaderName];
$cookieStore.remove('user');
$location.path("/login");
};
© 2015 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
The Art of AngularJS in 2015
The Art of AngularJS in 2015
Google's Recommendations for Angular App Structure
The Art of AngularJS in 2015
© 2015 Raible Designs
Testing
Karma - test runner, framework agnostic

Jasmine - unit tests, framework agnostic

Protractor - integration tests, angular specific

Lineman - productivity, framework agnostic
© 2015 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
});
}));
© 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');
});
});
});
© 2015 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);
});
});
© 2015 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
© 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"
© 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"
© 2015 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}']
}
},
© 2015 Raible Designs
Gruntfile.js
useminPrepare: {
html: 'app/index.html'
},
usemin: {
html: ['dist/index.html']
},
uglify: {
options: {
report: 'min',
mangle: false
}
}
});
© 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'
]);
};
© 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>
© 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>
© 2015 Raible Designs
After Grunt
http://raibledesigns.com/rd/entry/using_grunt_with_angularjs_for
© 2015 Raible Designs
You shouldn’t have to worry about FEO
http://raibledesigns.com/rd/entry/you_shouldn_t_have_to
© 2015 Raible Designs
HTTP/2 Performance Anti-Patterns?
Split dominant content domains

Reduce requests

	 Merging

	 Sprites

	 DataURIs
http://www.slideshare.net/andydavies
© 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']);
© 2015 Raible Designs
UI Bootstrap: Carousel
© 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>
© 2015 Raible Designs
Foundation for Apps http://foundation.zurb.com/apps
© 2015 Raible Designs
Foundation
© 2015 Raible Designs
Foundation
© 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>
© 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>
© 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);
}
}
© 2015 Raible Designs
Ionic Framework http://ionicframework.com
© 2015 Raible Designs#dv13javaweb$
My Ionic Experience
http://raibledesigns.com/rd/entry/developing_an_ios_native_app
© 2015 Raible Designs
JHipster http://jhipster.github.io/
© 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
© 2015 Raible Designs
JHipster
© 2015 Raible Designs
JHipster: Metrics
© 2015 Raible Designs
JHipster: Code Generation
© 2015 Raible Designs
JHipster: Code Generation
© 2015 Raible Designs
AngularJS Batarang
© 2015 Raible Designs
My Experience in 2013
Developing with AngularJS Series

Part I: The Basics

Part II: Dialogs and Data

Part III: Services

Part IV: Making it Pop

© 2015 Raible Designs#dv13javaweb$
My Experience in 2013
http://vimeo.com/mraible/angularjs-deep-dive
© 2015 Raible Designs
2015 AngularJS Tutorials
Getting Started with AngularJS

http://raibledesigns.com/rd/entry/getting_started_with_angularjs 

Testing AngularJS Applications

http://raibledesigns.com/rd/entry/testing_angularjs_applications
© 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
© 2015 Raible Designs
Angular 2.0
<input type="text" [value]="firstName">
<button (click)="addPerson()">Add</button>
<input type="checkbox" [checked]="someProperty">
© 2015 Raible Designs
Concepts Eliminated in 2.0
Controllers

Directive Definition Object

$scope

angular.module

jqLite
© 2015 Raible Designs
The Bad News
No 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
http://12factor.net/
© 2015 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
© 2015 Raible Designs
Shortcut to becoming an Angular Artist
JUST DO IT.
© 2015 Raible Designs
Contact Me!

http://raibledesigns.com

@mraible

Presentations

http://slideshare.net/mraible

Code

http://github.com/mraible
Questions?
© 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
© 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
© 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

More Related Content

What's hot (20)

PDF
Real World Web components
Jarrod Overson
 
PDF
The Art of Angular in 2016 - Devoxx UK 2016
Matt Raible
 
PDF
Gettings started with the superheroic JavaScript library AngularJS
Armin Vieweg
 
PDF
Testing Angular 2 Applications - HTML5 Denver 2016
Matt Raible
 
PDF
Web Components v1
Mike Wilcox
 
PDF
Get Hip with JHipster: Spring Boot + AngularJS + Bootstrap - Devoxx UK 2016
Matt Raible
 
PDF
Getting Started with Angular - Stormpath Webinar, January 2017
Matt Raible
 
PDF
Web Components
Nikolaus Graf
 
PDF
Great Responsive-ability Web Design
Mike Wilcox
 
PDF
What's New in Spring 3.1
Matt Raible
 
PDF
Accessibility - A feature you can build
Monika Piotrowicz
 
PDF
Web Frameworks of the Future: Flex, GWT, Grails and Rails
Matt Raible
 
PDF
Get Hip with JHipster - Colorado Springs OSS Meetup April 2016
Matt Raible
 
PDF
The Art of AngularJS - DeRailed 2014
Matt Raible
 
PDF
Real World Web Standards
gleddy
 
PDF
Java Web Application Security - Denver JUG 2013
Matt Raible
 
PDF
The Complementarity of React and Web Components
Andrew Rota
 
PDF
Chrome enchanted 2015
Chang W. Doh
 
PDF
Building Progressive Web Apps for Android and iOS
FITC
 
PDF
Building Mobile Applications with Ionic
Morris Singer
 
Real World Web components
Jarrod Overson
 
The Art of Angular in 2016 - Devoxx UK 2016
Matt Raible
 
Gettings started with the superheroic JavaScript library AngularJS
Armin Vieweg
 
Testing Angular 2 Applications - HTML5 Denver 2016
Matt Raible
 
Web Components v1
Mike Wilcox
 
Get Hip with JHipster: Spring Boot + AngularJS + Bootstrap - Devoxx UK 2016
Matt Raible
 
Getting Started with Angular - Stormpath Webinar, January 2017
Matt Raible
 
Web Components
Nikolaus Graf
 
Great Responsive-ability Web Design
Mike Wilcox
 
What's New in Spring 3.1
Matt Raible
 
Accessibility - A feature you can build
Monika Piotrowicz
 
Web Frameworks of the Future: Flex, GWT, Grails and Rails
Matt Raible
 
Get Hip with JHipster - Colorado Springs OSS Meetup April 2016
Matt Raible
 
The Art of AngularJS - DeRailed 2014
Matt Raible
 
Real World Web Standards
gleddy
 
Java Web Application Security - Denver JUG 2013
Matt Raible
 
The Complementarity of React and Web Components
Andrew Rota
 
Chrome enchanted 2015
Chang W. Doh
 
Building Progressive Web Apps for Android and iOS
FITC
 
Building Mobile Applications with Ionic
Morris Singer
 

Viewers also liked (11)

PDF
CSS3 Media Queries
Russ Weakley
 
PDF
Beyond Media Queries: Anatomy of an Adaptive Web Design
Brad Frost
 
PPTX
Media queries and frameworks
Nicole Ryan
 
PPTX
AngularJS best practices
Filip Bruun Bech-Larsen
 
PDF
AngularJS Best Practices
Betclic Everest Group Tech Team
 
PDF
AngularJS best-practices
Henry Tao
 
PPTX
Mobile Email Design, Strategies, Workflow and Best Practices
Litmus
 
PDF
CSS Best practice
Russ Weakley
 
PDF
New Features in Angular 1.5
Kenichi Kanai
 
PPT
Css best practices style guide and tips
Chris Love
 
PPTX
AngularJS Best Practices
Narek Mamikonyan
 
CSS3 Media Queries
Russ Weakley
 
Beyond Media Queries: Anatomy of an Adaptive Web Design
Brad Frost
 
Media queries and frameworks
Nicole Ryan
 
AngularJS best practices
Filip Bruun Bech-Larsen
 
AngularJS Best Practices
Betclic Everest Group Tech Team
 
AngularJS best-practices
Henry Tao
 
Mobile Email Design, Strategies, Workflow and Best Practices
Litmus
 
CSS Best practice
Russ Weakley
 
New Features in Angular 1.5
Kenichi Kanai
 
Css best practices style guide and tips
Chris Love
 
AngularJS Best Practices
Narek Mamikonyan
 
Ad

Similar to The Art of AngularJS in 2015 (20)

PPTX
Utilizing jQuery in SharePoint: Get More Done Faster
Mark Rackley
 
PDF
The Art of Angular in 2016 - Devoxx France 2016
Matt Raible
 
PDF
Going web native
Marcus Hellberg
 
PDF
The Modern Java Web Developer - Denver JUG 2013
Matt Raible
 
PPTX
Adobe & HTML5
Terry Ryan
 
ODP
WordPress Accessibility: WordCamp Chicago
Joseph Dolson
 
KEY
New Perspectives on Performance
mennovanslooten
 
PDF
Front End Development for Back End Developers - Denver Startup Week 2017
Matt Raible
 
PDF
The Art of Angular in 2016 - vJUG24
Matt Raible
 
PDF
How You Convince Your Manager To Adopt Scala.js in Production
BoldRadius Solutions
 
PPTX
Tulsa TechFest 2015 Awesomely Simple SharePoint Solutions
April Dunnam
 
PDF
Headless Drupal
drubb
 
PDF
Twitter bootstrap on rails
Masakuni Kato
 
PDF
Vaadin Flow - JavaLand 2018
Peter Lehto
 
KEY
RWD in the Wild
Rich Quick
 
PDF
Introduction to Ruby on Rails
Diki Andeas
 
PPTX
15 Drupal Modules You've Probably Overlooked but Shouldn't
Chris Sloan
 
PPTX
Ruby on Rails + AngularJS + Twitter Bootstrap
Marcio Marinho
 
PPTX
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
JavaScripters Community
 
PPTX
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
murtazahaveliwala
 
Utilizing jQuery in SharePoint: Get More Done Faster
Mark Rackley
 
The Art of Angular in 2016 - Devoxx France 2016
Matt Raible
 
Going web native
Marcus Hellberg
 
The Modern Java Web Developer - Denver JUG 2013
Matt Raible
 
Adobe & HTML5
Terry Ryan
 
WordPress Accessibility: WordCamp Chicago
Joseph Dolson
 
New Perspectives on Performance
mennovanslooten
 
Front End Development for Back End Developers - Denver Startup Week 2017
Matt Raible
 
The Art of Angular in 2016 - vJUG24
Matt Raible
 
How You Convince Your Manager To Adopt Scala.js in Production
BoldRadius Solutions
 
Tulsa TechFest 2015 Awesomely Simple SharePoint Solutions
April Dunnam
 
Headless Drupal
drubb
 
Twitter bootstrap on rails
Masakuni Kato
 
Vaadin Flow - JavaLand 2018
Peter Lehto
 
RWD in the Wild
Rich Quick
 
Introduction to Ruby on Rails
Diki Andeas
 
15 Drupal Modules You've Probably Overlooked but Shouldn't
Chris Sloan
 
Ruby on Rails + AngularJS + Twitter Bootstrap
Marcio Marinho
 
JavaScripters Event Oct 22, 2016 · 2:00 PM: Common Mistakes made by Angular D...
JavaScripters Community
 
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
murtazahaveliwala
 
Ad

More from Matt Raible (20)

PDF
Keep Identities in Sync the SCIMple Way - ApacheCon NA 2022
Matt Raible
 
PDF
Micro Frontends for Java Microservices - Belfast JUG 2022
Matt Raible
 
PDF
Micro Frontends for Java Microservices - Dublin JUG 2022
Matt Raible
 
PDF
Micro Frontends for Java Microservices - Cork JUG 2022
Matt Raible
 
PDF
Comparing Native Java REST API Frameworks - Seattle JUG 2022
Matt Raible
 
PDF
Reactive Java Microservices with Spring Boot and JHipster - Spring I/O 2022
Matt Raible
 
PDF
Comparing Native Java REST API Frameworks - Devoxx France 2022
Matt Raible
 
PDF
Lock That Sh*t Down! Auth Security Patterns for Apps, APIs, and Infra - Devne...
Matt Raible
 
PDF
Native Java with Spring Boot and JHipster - Garden State JUG 2021
Matt Raible
 
PDF
Java REST API Framework Comparison - PWX 2021
Matt Raible
 
PDF
Web App Security for Java Developers - PWX 2021
Matt Raible
 
PDF
Mobile App Development with Ionic, React Native, and JHipster - Connect.Tech ...
Matt Raible
 
PDF
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Joker...
Matt Raible
 
PDF
Web App Security for Java Developers - UberConf 2021
Matt Raible
 
PDF
Java REST API Framework Comparison - UberConf 2021
Matt Raible
 
PDF
Native Java with Spring Boot and JHipster - SF JUG 2021
Matt Raible
 
PDF
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Sprin...
Matt Raible
 
PDF
Reactive Java Microservices with Spring Boot and JHipster - Denver JUG 2021
Matt Raible
 
PDF
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Matt Raible
 
PDF
JHipster and Okta - JHipster Virtual Meetup December 2020
Matt Raible
 
Keep Identities in Sync the SCIMple Way - ApacheCon NA 2022
Matt Raible
 
Micro Frontends for Java Microservices - Belfast JUG 2022
Matt Raible
 
Micro Frontends for Java Microservices - Dublin JUG 2022
Matt Raible
 
Micro Frontends for Java Microservices - Cork JUG 2022
Matt Raible
 
Comparing Native Java REST API Frameworks - Seattle JUG 2022
Matt Raible
 
Reactive Java Microservices with Spring Boot and JHipster - Spring I/O 2022
Matt Raible
 
Comparing Native Java REST API Frameworks - Devoxx France 2022
Matt Raible
 
Lock That Sh*t Down! Auth Security Patterns for Apps, APIs, and Infra - Devne...
Matt Raible
 
Native Java with Spring Boot and JHipster - Garden State JUG 2021
Matt Raible
 
Java REST API Framework Comparison - PWX 2021
Matt Raible
 
Web App Security for Java Developers - PWX 2021
Matt Raible
 
Mobile App Development with Ionic, React Native, and JHipster - Connect.Tech ...
Matt Raible
 
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Joker...
Matt Raible
 
Web App Security for Java Developers - UberConf 2021
Matt Raible
 
Java REST API Framework Comparison - UberConf 2021
Matt Raible
 
Native Java with Spring Boot and JHipster - SF JUG 2021
Matt Raible
 
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Sprin...
Matt Raible
 
Reactive Java Microservices with Spring Boot and JHipster - Denver JUG 2021
Matt Raible
 
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Matt Raible
 
JHipster and Okta - JHipster Virtual Meetup December 2020
Matt Raible
 

Recently uploaded (20)

PDF
Design Thinking basics for Engineers.pdf
CMR University
 
PPTX
MODULE 04 - CLOUD COMPUTING AND SECURITY.pptx
Alvas Institute of Engineering and technology, Moodabidri
 
PPTX
Biosensors, BioDevices, Biomediccal.pptx
AsimovRiyaz
 
PPTX
Distribution reservoir and service storage pptx
dhanashree78
 
PDF
AI TECHNIQUES FOR IDENTIFYING ALTERATIONS IN THE HUMAN GUT MICROBIOME IN MULT...
vidyalalltv1
 
PPTX
Mechanical Design of shell and tube heat exchangers as per ASME Sec VIII Divi...
shahveer210504
 
PPTX
MODULE 05 - CLOUD COMPUTING AND SECURITY.pptx
Alvas Institute of Engineering and technology, Moodabidri
 
PDF
Water Industry Process Automation & Control Monthly July 2025
Water Industry Process Automation & Control
 
PPTX
Knowledge Representation : Semantic Networks
Amity University, Patna
 
PDF
3rd International Conference on Machine Learning and IoT (MLIoT 2025)
ClaraZara1
 
PDF
REINFORCEMENT LEARNING IN DECISION MAKING SEMINAR REPORT
anushaashraf20
 
PDF
Basic_Concepts_in_Clinical_Biochemistry_2018كيمياء_عملي.pdf
AdelLoin
 
PPTX
OCS353 DATA SCIENCE FUNDAMENTALS- Unit 1 Introduction to Data Science
A R SIVANESH M.E., (Ph.D)
 
PPTX
Water Resources Engineering (CVE 728)--Slide 3.pptx
mohammedado3
 
PDF
aAn_Introduction_to_Arcadia_20150115.pdf
henriqueltorres1
 
PDF
MODULE-5 notes [BCG402-CG&V] PART-B.pdf
Alvas Institute of Engineering and technology, Moodabidri
 
PDF
Reasons for the succes of MENARD PRESSUREMETER.pdf
majdiamz
 
PPTX
DATA BASE MANAGEMENT AND RELATIONAL DATA
gomathisankariv2
 
PPT
Footbinding.pptmnmkjkjkknmnnjkkkkkkkkkkkkkk
mamadoundiaye42742
 
PPTX
Numerical-Solutions-of-Ordinary-Differential-Equations.pptx
SAMUKTHAARM
 
Design Thinking basics for Engineers.pdf
CMR University
 
MODULE 04 - CLOUD COMPUTING AND SECURITY.pptx
Alvas Institute of Engineering and technology, Moodabidri
 
Biosensors, BioDevices, Biomediccal.pptx
AsimovRiyaz
 
Distribution reservoir and service storage pptx
dhanashree78
 
AI TECHNIQUES FOR IDENTIFYING ALTERATIONS IN THE HUMAN GUT MICROBIOME IN MULT...
vidyalalltv1
 
Mechanical Design of shell and tube heat exchangers as per ASME Sec VIII Divi...
shahveer210504
 
MODULE 05 - CLOUD COMPUTING AND SECURITY.pptx
Alvas Institute of Engineering and technology, Moodabidri
 
Water Industry Process Automation & Control Monthly July 2025
Water Industry Process Automation & Control
 
Knowledge Representation : Semantic Networks
Amity University, Patna
 
3rd International Conference on Machine Learning and IoT (MLIoT 2025)
ClaraZara1
 
REINFORCEMENT LEARNING IN DECISION MAKING SEMINAR REPORT
anushaashraf20
 
Basic_Concepts_in_Clinical_Biochemistry_2018كيمياء_عملي.pdf
AdelLoin
 
OCS353 DATA SCIENCE FUNDAMENTALS- Unit 1 Introduction to Data Science
A R SIVANESH M.E., (Ph.D)
 
Water Resources Engineering (CVE 728)--Slide 3.pptx
mohammedado3
 
aAn_Introduction_to_Arcadia_20150115.pdf
henriqueltorres1
 
MODULE-5 notes [BCG402-CG&V] PART-B.pdf
Alvas Institute of Engineering and technology, Moodabidri
 
Reasons for the succes of MENARD PRESSUREMETER.pdf
majdiamz
 
DATA BASE MANAGEMENT AND RELATIONAL DATA
gomathisankariv2
 
Footbinding.pptmnmkjkjkknmnnjkkkkkkkkkkkkkk
mamadoundiaye42742
 
Numerical-Solutions-of-Ordinary-Differential-Equations.pptx
SAMUKTHAARM
 

The Art of AngularJS in 2015

  • 1. Photos by The Art of in 2015 Matt Raible • http://raibledesigns.com
  • 2. © 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
  • 3. © 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/
  • 4. © 2015 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
  • 5. © 2015 Raible Designs Jobs on Dice.com January 2015 0 225 450 675 900 Backbone Angular Em ber Knockout React
  • 6. © 2015 Raible Designs LinkedIn Skills January 2015 0 25,000 50,000 75,000 100,000 Backbone Angular Knockout Em ber React
  • 7. © 2015 Raible Designs Google Trends
  • 8. © 2015 Raible Designs Indeed Job Trends Absolute Relative
  • 9. © 2015 Raible Designs Stack Overflow
  • 11. © 2015 Raible Designs Who wants to learn ?
  • 12. © 2015 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
  • 13. © 2015 Raible Designs The History of AngularJS 0 4500 9000 13500 18000 Lines of Code 17,000 1,000 AngularJS GWT
  • 14. © 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>
  • 15. © 2015 Raible Designs Architecture Principles Structure Testability Boilerplate D.R.Y.
  • 16. © 2015 Raible Designs Code Organization Start with Angular Seed* * more options to be discussed later… git clone https://github.com/angular/angular-seed.git
  • 17. © 2015 Raible Designs Quick Demo
  • 18. © 2015 Raible Designs App Definition var app = angular.module('myApp', []); <!DOCTYPE html> <html ng-app="myApp">
  • 19. © 2015 Raible Designs App Definition with separate files app.js controllers.js angular.module('myApp', ['ngRoute', 'myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers' ]) angular.module('myApp.controllers', []). controller('MyCtrl1', [function() { }])
  • 20. © 2015 Raible Designs Model View Controller
  • 21. © 2015 Raible Designs Data Binding friend.js friend.html $scope.friend = { name: "Fernand" }; {{friend.name}} // 1-way <input ng-model="friend.name"> // 2-way
  • 22. © 2015 Raible Designs Solving FOUC This 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>
  • 23. © 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>
  • 24. © 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>
  • 25. © 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}}' }; });
  • 26. © 2015 Raible Designs Built-In Directives ng-href ng-src ng-disabled ng-checked ng-readonly ng-selected ng-class ng-style
  • 27. © 2015 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'}); });
  • 28. © 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);
  • 29. © 2015 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 }; });
  • 30. © 2015 Raible Designs $q myApp.controller('HelloCtrl', function($scope, HelloWorld) { HelloWorld.getMessages().then(function(messages) { $scope.messages = messages; }); });
  • 31. © 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("/"); }); }; })
  • 32. © 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' }}
  • 33. © 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('!'); }] )
  • 34. © 2015 Raible Designs Routing: Navigation $rootScope.logout = function () { delete $rootScope.user; delete $http.defaults.headers.common[xAuthTokenHeaderName]; $cookieStore.remove('user'); $location.path("/login"); };
  • 35. © 2015 Raible Designs Routing: Navigation $rootScope.logout = function () { delete $rootScope.user; delete $http.defaults.headers.common[xAuthTokenHeaderName]; $cookieStore.remove('user'); $location.path("/login"); };
  • 36. © 2015 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
  • 39. Google's Recommendations for Angular App Structure
  • 41. © 2015 Raible Designs Testing Karma - test runner, framework agnostic Jasmine - unit tests, framework agnostic Protractor - integration tests, angular specific Lineman - productivity, framework agnostic
  • 42. © 2015 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 }); }));
  • 43. © 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'); }); }); });
  • 44. © 2015 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); }); });
  • 45. © 2015 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
  • 46. © 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"
  • 47. © 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"
  • 48. © 2015 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}'] } },
  • 49. © 2015 Raible Designs Gruntfile.js useminPrepare: { html: 'app/index.html' }, usemin: { html: ['dist/index.html'] }, uglify: { options: { report: 'min', mangle: false } } });
  • 50. © 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' ]); };
  • 51. © 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>
  • 52. © 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>
  • 53. © 2015 Raible Designs After Grunt http://raibledesigns.com/rd/entry/using_grunt_with_angularjs_for
  • 54. © 2015 Raible Designs You shouldn’t have to worry about FEO http://raibledesigns.com/rd/entry/you_shouldn_t_have_to
  • 55. © 2015 Raible Designs HTTP/2 Performance Anti-Patterns? Split dominant content domains Reduce requests Merging Sprites DataURIs http://www.slideshare.net/andydavies
  • 56. © 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']);
  • 57. © 2015 Raible Designs UI Bootstrap: Carousel
  • 58. © 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>
  • 59. © 2015 Raible Designs Foundation for Apps http://foundation.zurb.com/apps
  • 60. © 2015 Raible Designs Foundation
  • 61. © 2015 Raible Designs Foundation
  • 62. © 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>
  • 63. © 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>
  • 64. © 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); } }
  • 65. © 2015 Raible Designs Ionic Framework http://ionicframework.com
  • 66. © 2015 Raible Designs#dv13javaweb$ My Ionic Experience http://raibledesigns.com/rd/entry/developing_an_ios_native_app
  • 67. © 2015 Raible Designs JHipster http://jhipster.github.io/
  • 68. © 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
  • 69. © 2015 Raible Designs JHipster
  • 70. © 2015 Raible Designs JHipster: Metrics
  • 71. © 2015 Raible Designs JHipster: Code Generation
  • 72. © 2015 Raible Designs JHipster: Code Generation
  • 73. © 2015 Raible Designs AngularJS Batarang
  • 74. © 2015 Raible Designs My Experience in 2013 Developing with AngularJS Series Part I: The Basics
 Part II: Dialogs and Data
 Part III: Services
 Part IV: Making it Pop

  • 75. © 2015 Raible Designs#dv13javaweb$ My Experience in 2013 http://vimeo.com/mraible/angularjs-deep-dive
  • 76. © 2015 Raible Designs 2015 AngularJS Tutorials Getting Started with AngularJS http://raibledesigns.com/rd/entry/getting_started_with_angularjs Testing AngularJS Applications http://raibledesigns.com/rd/entry/testing_angularjs_applications
  • 77. © 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
  • 78. © 2015 Raible Designs Angular 2.0 <input type="text" [value]="firstName"> <button (click)="addPerson()">Add</button> <input type="checkbox" [checked]="someProperty">
  • 79. © 2015 Raible Designs Concepts Eliminated in 2.0 Controllers Directive Definition Object $scope angular.module jqLite
  • 80. © 2015 Raible Designs The Bad News No 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
  • 82. © 2015 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
  • 83. © 2015 Raible Designs Shortcut to becoming an Angular Artist JUST DO IT.
  • 84. © 2015 Raible Designs Contact Me! http://raibledesigns.com @mraible Presentations http://slideshare.net/mraible Code http://github.com/mraible Questions?
  • 85. © 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
  • 86. © 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
  • 87. © 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