Miško Hevery
- Intel (Hardware Engineer)
- Adobe
- Sun
Passion: Better software through testing
frustration
Meet: AngularJS
- Open Source hobby project
- Angular 0.9 - Dragon-Breath (Oktober 2010)
- Bet: Complete rebuild in 2 weeks
- Lost: Done in 3 weeks
- Javascript: 17.000 lines -> 1000 lines
- Google DoubleClick
- 2 years / 3 developers
- Angular 1.0 (june 2012)
Angular 1.2
> 10 teammembers
- 5 full time developers
- Documentation
- Speakers
- 364 contributors
Stable
Updates less often than JQuery
Stable release and unstable release
Unstable != Unstable
new features are still subject for change
Superheroic JavaScript MVW Framework
"AngularJS is what HTML would have been, had it been designed for building web-apps"
"When you develop in Angular, you are developing in a better browser!"
"Pretty sure that HTML6 is going under the codename @angularjs!"
AngularJS?
!= library
= Framework
"Better Browser"
S.P.A.
Single Page Applications
Why?
- Dynamic websites/webapplications
- Declarative templating with databinding
- DOM manipulation != Application Logic
- Extend HTML
- Decouple client side from server side
- Modular
- Testable
- Plain Javascript
Forget everything you know
About JQuery
Seriously !!!
Forget JQuery
Sins with/of JQuery
- Don't Design Your Page, then Change it with DOM Manipulations
- Don't Augment JQuery with AngularJS
- Always Think in Terms of Architecture
-
The View is the "Official Record"
- Databinding
- Distinct Model Layer
- Seperation of concerns
- Dependency Injection
- Test Driven development
Imperative
VS
Declarative
How VS What
JQuery VS AngularJS
<input id="toggleShowHide" type="checkbox"> <div id=”specialParagraph”> This content will disappear and reappear if you click the checkbox above
</div>
<script>
$(function() {
function toggle() {var isChecked = $('#toggleShowHide').is(':checked');
var specialParagraph = $('#specialParagraph');if (isChecked) { specialParagraph.show(); }
else { specialParagraph.hide(); }
}
$('#toggleShowHide').change(function() {
toggle();
});
toggle();
});
</script>
AngularJS
<input ng-model="showSpecial" type="checkbox">
<div ng-show=”showSpecial”> This content will disappear and reappear if you click the checkbox above </div>
Do not include JQuery
DOM manipulation
Do you really need a JQuery plugin?
Wrap it within a Directive
BUT:
"Conceptually, Directives are NOT packaged JQuery"
It's usually easier to refactor the plugin the "Angular Way"
Or is it?
Teaching browsers new Tricks
-
Data Binding
- Filters
-
DI (Dependency Injection)
-
Directives
-
Animations
- HTTP/Resource (REST)
Data Binding
<h1> {{ person.firstname }} <h1>
<h1 ng-bind="person.firstname > </h1>
<p> 1 + 1 = {{ 1 + 1 }} </p>
Filters
<ul>
<li ng-repeat="person in persons | orderBy: 'lastname'">
{{ person.firstname }}
, {{ person.lastname | uppercase }}
</li>
</ul>
- currency
- date
- filter
- json
- limitTo
- lowercase
- number
- orderBy
- uppercase
Dependency Injection
/scripts/app.js
angular.module('railsApp', ['ngRoute', 'ngResource', 'ui-bootstrap']);
/scripts/controllers/main.js
angular.module('railsApp') .controller('MainCtrl', function($scope, $routeParam, Person){ $scope.person = Person.get($routeParams.personId);
$scope.save = function(person){ Person.save(person);
}
});
-
Loose coupling
- Testing
Directives
"A way to teach HTML new Tricks"
"Create your own HTML tags"
"Directive === Reusable Component"
"Register Behavior"
"Transform / Manipulate the DOM"
Directives
Element
<ng-view></ng-view>
Attribute
<div ng-view></div>
Class
<div class="ng-view"><div>
Sample
<tabset>
<tab ng-repeat="tab in tabs" heading="{{tab.title}}"
active="tab.active" disabled="tab.disabled">
{{tab.content}}
</tab>
</tabset>
Core Directives
- ng-app
-
ng-controller
- ng-include
-
ng-repeat
- ng-switch
- ng-view
Display Directives
- ng-class
- ng-class-even
- ng-class-odd
- ng-cloak
- ng-hide
- ng-if
- ng-show
- ng-style
Event Directives
- ng-change
- ng-checked
- ng-click
- ng-dblclick
- ng-keydown|press|up
- ng-mousedown|enter|leave|move|over|up
- ng-selected
- ng-submit
Community Directives
- angular-ui
- ui-utils
- ui-modules
- ui-bootstrap
- ng-grid
- ui-router
-
angular-leaflet
- Restangular
- angular-Translate
custom directive
-
The place for DOM manipulation
- Pretty complex at first
- Usually there's already a community plugin
Don't get
A lot is possible without custom directives!!
Animations
angular.module('railsApp', ['ngAnimate']);
- CSS3 animations
- Possible with javascript
- animate.css
Resource
- ngResource
- Interact with RESTFul serverside data sources
-
JSON
-
Promises
RAILS RESTful endpoint
class PersonController < ApplicationController
def index
@persons = Person.get(params[:person])
respond_to do |format|
format.html # index.html.erb
format.json { render json: @persons, root: false }
end
end
# other actions
end
Resource
angular.module('railsApp', ['ngResource'])
.factory('Person', function person($resource){
return $resource('/persons/:id', {id: '@id'}{
// DEFAULT IMPLEMENTATION OF $RESOURCE
// 'get': {method:'GET'}, // 'save': {method:'POST'}, // 'query': {method:'GET', isArray:true}, // 'remove': {method:'DELETE'}, // 'delete': {method:'DELETE'} }
}
In use
angular.module('railsApp')
.controller('MainCtrl', function($scope, Person){
$scope.persons = Person.query();
$scope.add = function(newPerson){
Person.save(newPerson);
}
}
Application structure
Module
Application Level Module
angular.module('railsApp', []);
Module per feature
- Users
- Routing
- Admin
- Portfolio
Angular Modules
angular.module('railsApp', ['ngAnimate', 'ngRoute', 'ngResource']);
Config
app.js
angular.module('railsApp', []);
index.html
<!DOCTYPE HTML> <html ng-app="railsApp"> <head>
<title>AngularJS with Rails</title>
</head>
<body>
<h1> {{ rails.awesomeTitle }} </h1>
<script src="scripts/vendor/angular/angular.min.js">
<script src="scripts/app.js"></script>
</body>
</html>
View
HTML
Templates
!! Declarative !!
$scope
$scope.person = {
firstName: 'Jan'
lastName: 'Progger'
}
controller.js
<h1> {{ person.firstname }} </h1>
views/main.html
Controller
scripts/controllers/main.js
"Expose model objects and methods to the View "
-
View specific code
- NO DOM manipulation
angular.module('railsApp') .controller('MainCtrl', function ($scope, Person) { $scope.persons = Person.getPersons();
$scope.addPerson = function(newPerson){
Person.save(newPerson)
} });
Controller as >= 1.2
views/main.html
<div ng-controller="MainCtrl as main">
<p> {{ main.person.firstname }} {{ main.person.firstname }} </p>
</div>
scripts/controllers/main.js
angular.module('railsApp') .controller('MainCtrl', function () {
this.person = { firstName: 'Jan' lastName: 'Progger' }
});
Routing
-
Deep Linking
-
History (back button)
angular.module('railsApp', ['ngRoute']) .config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' })
.when('/person/:name', { templateUrl: 'views/person.html', controller: 'PersonCtrl' }) .otherwise({ redirectTo: '/' }); });
Services
- View independent methods
-
Singleton
- Constant
- Decorator
-
Factory
- Provider
- Service
- Value
Factory
scripts/services/person.js
angular.module('railsApp').factory('Person', function(){
var personFactory = {};
var persons = {
'77': {
firstName: 'Jan',
lastName: 'Progger
}
}
personFactory.get = function(personId){
return persons[personId];
}
return personFactory;
});
Constant
scripts/services/constants.js
angular.module('railsApp').constant('COMPANY', 'Gino B.V.');
angular.module('railsApp').constant('THE_ANSWER', 42);
scripts/controllers/main.js
angular.module('railsApp').controller('MainCtrl',
function(COMPANY, THE_ANSWER){
console.log('Company is ' + COMPANY);
console.log('The all knowing answer is: ' + THE_ANSWER);
}
Directory structure
- /images
- /scripts
- /controllers
- /directives
- /services
- app.js
- /styles
- /views
- main.html
- person.html
- index.html
Testing
Test Runner: Karma testrunner
Unit Testing: Jasmine
End-2-End testing: Protractor
Yeoman
angular-generator
Bower: Package manager
Grunt: Build tool
Awesome workflow
yo angular demo
------
yo angular:controller person
------
yo angular:route myRoute --coffee
------
yo angular:factory myFactory --minsafe
bower update
------
bower search angular
------
bower install angular --save
grunt test
----------
grunt build
----------
grunt server
- Phonegap
- html5
- CSS3
-
ng-touch
Yeah great, but who else uses it?
- Google Feedback
- Google DoubleClick
- PS3: Youtube browser
- Devoxx
- Plunker!
Getting Started
Questions?
AngularJS is Superheroic
By Arjen
AngularJS is Superheroic
Short presentation about AngularJS. Made for the Ruby on Rails Group in Groningen. (Combined a lot of material, from a lot of different sources)
- 3,458