SlideShare a Scribd company logo
HOW ANGULAR2 CAN
IMPROVE YOUR
ANGULARJS APPS
TODAY!
Nir Kaufman
NIR KUFMN
Nir Kaufman
- Doing Angular for years
- Wrote a book about Angular2
- Play the electric Bass
Head of Angular Development @ 500Tech
*This picture have been retouched
the actual speaker may look different
ARE YOU
READY FOR
MIGRATION?
How Angular2 Can Improve Your AngularJS Apps Today!
UNAGENDA
I AM NOT GOING TO TALK ABOUT
- TypeScript
- Angular2 upgrade module
- Ng-forward library
- Data flow (Redux, RxJs)
- Angular 1.5 new Component API
BE REALISTIC.
GET READY FOR
THE MIGRATION
BUT…
DON’T FORCE
ANGULAR1 TO
BEHAVE LIKE
ANGULAR2
IT WON’T WORK.
WHAT SHOULD
YOU DO?
APPLY SOME
ANGULAR2 IDEAS
IT WILL IMPROVE
YOUR APP DESIGN
AND GET YOU
READY FOR THE
FUTURE
WINWIN SITUATION
I WILL TALK ABOUT
- Embracing Modules
- Using Classes
- Decoupling from Framework API
- Components as UI building blocks
WAIT A SECOND…
THESE ARE NOT
ANGULAR2 IDEAS!
THAT’S TRUE.
THESE ARE GOOD
PRACTICES
THAT YOU CAN
COMPLETE IN
ONE SPRINT
How Angular2 Can Improve Your AngularJS Apps Today!
https://github.com/nirkaufman/ng1-coffee-shop
GRAB THE CODE
http://tinyurl.com/hdmqrem
REVIEW THE APP
EVERYTHING
IS A MODULE
$ git checkout 01_modules
USE A MODULE LOADER
Integrate a module bundler and an ES6
compiler to use javaScript modules.
http://webpack.github.io/
MODULE LOADER
module.exports = {

entry: 'index.js',



// configure loaders

module: {

loaders: [

{

test: /.js$/,

exclude: /node_modules/,

loader: "babel",

query: {presets: ['es2015', 'stage-1']}

},



// load css as inline styles

{test: /.css$/, loader: "style!css"}

]

}

};
new webpack.config.js
<script src="bundle.js"></script>
old index.html
<!-- load core scripts -->

<script src="../node_modules/angular/angular.js"></script>

<script src="../node_modules/angular-ui-router/release/angular-ui-
router.js"></script>

<script src="index.js"></script>



<!-- load services -->

<script src="services/logger.factory.js"></script>

<script src="services/storage.service.js"></script>

<script src="services/orders.service.js"></script>



<!-- load filters -->

<script src="filters/paid-orders.filter.js"></script>



<!-- load directives -->

<script src="directives/simple-table/simple-table.js"></script>



<!-- load controllers -->

<script src="states/home.controller.js"></script>

<script src="states/log.controller.js"></script>
<body>
<script src=“bundle.js"></script>
</body>
new index.html
import 'angular';

import 'angular-ui-router';

import './assets/index.css';





import services from './services/services.module';

import filters from './filters/filters.module'

import directives from './directives/directives.module';

import states from './states/state.module';
new index.js
BUNDLE != CONTACT
old log.controller.js
(function (angular) {



angular.module('app')

.controller('LogController', function ($scope, $window, Orders, Storage) {

$scope.orders = Orders.getOrders();



$scope.clearHistory = function () {



if ($scope.orders.length === 0) {

return;

}



var result = $window.confirm("Clear History?");

if (result) {

Storage.clear();

$scope.orders = [];

}

}

})



}(window.angular));
new log.controller.js
export function LogController ($scope, $window, Orders, Storage) {



$scope.orders = Orders.getOrders();



$scope.clearHistory = function () {



if ($scope.orders.length === 0) {

return;

}



var result = $window.confirm("Clear History?");

if (result) {

Storage.clear();

$scope.orders = [];

}

}

}
MODULAR APPROACH
old storage.service.js
(function (angular) {


angular.module('app')

.service('Storage', function () {



var ORDERS_KEY = "ORDERS";

this.store = localStorage;



this.getOrders = function () {

return JSON.parse(this.store.getItem(ORDERS_KEY)) || [];

};



this.saveOrders = function (orders) {

this.store.setItem(ORDERS_KEY, JSON.stringify(orders))

};



this.clear = function () {

this.store.clear();

}

})


}(window.angular));
new storage.service.js
export function Storage () {



var ORDERS_KEY = "ORDERS";

this.store = localStorage;



this.getOrders = function () {

return JSON.parse(this.store.getItem(ORDERS_KEY)) || [];

};



this.saveOrders = function (orders) {

this.store.setItem(ORDERS_KEY, JSON.stringify(orders))

};

}
import {Storage} from './storage.service';



export default angular.module('services', [])

.service('Storage', Storage)
new service.module.js
old index.js
(function (angular) {



angular.module('app', ['ui.router'])

.config(function ($stateProvider, $urlRouterProvider) {



$urlRouterProvider.otherwise("/");



$stateProvider

.state('home', {

url: '/',

templateUrl: 'templates/home.html',

controller: 'HomeController'

})

.state('log', {

url: '/log',

templateUrl: 'templates/log.html',

controller: 'LogController'

})

});


}(window.angular)
new index.js
import 'angular';

import 'angular-ui-router';

import ‘./assets/index.css';


import services from './services/services.module';

import filters from './filters/filters.module'

import directives from './directives/directives.module';

import states from './states/state.module';

import {routes} from './config/routes';



angular.module('app', [

'ui.router',

services.name,

directives.name,

filters.name,

states.name
]).config(routes);



// bootstrap angular

angular.element(document).ready(function () {

angular.bootstrap(document, ['app']);

});
new routes.js
export function routes($stateProvider, $urlRouterProvider) {



$urlRouterProvider.otherwise("/");



// configure application routes

$stateProvider

.state('home', {

url: '/',

templateUrl: 'templates/home.html',

controller: 'HomeController'

})



.state('log', {

url: '/log',

templateUrl: 'templates/log.html',

controller: 'LogController'

})

}
EVERYTHING
IS A CLASS
$ git checkout 02_classes
MOVE FORWARD TO ES6
You can adopt the new syntax slowly. Start
by using classes instead of functions.
http://babeljs.io/
PLAIN SERVICES
old storage.service.js
export function Storage () {



var ORDERS_KEY = "ORDERS";

this.store = localStorage;



this.getOrders = function () {

return JSON.parse(this.store.getItem(ORDERS_KEY)) || [];

};



this.saveOrders = function (orders) {

this.store.setItem(ORDERS_KEY, JSON.stringify(orders))

};

}
new storage.service.js
export class Storage {



constructor() {

this.ORDERS_KEY = "ORDERS";

this.store = localStorage;

}



getOrders() {

return JSON.parse(this.store.getItem(this.ORDERS_KEY)) || [];

};



saveOrders(orders) {

this.store.setItem(this.ORDERS_KEY, JSON.stringify(orders))

};

}
ANGULAR FILTERS
old paid-orders.filter.js
export function paidOrders() {


return function (orders) {

return orders.filter(order => order.paid === false)

}


}
import {paidOrders} from './paid-orders.filter';



export default angular.module('filters', [])

.filter('paidOrders',paidOrders);
old filters.module.js
new paid-orders.filter.js
export class PaidOrders {



static transform () {

return (orders) => orders.filter(order => order.paid === false)

}

}
import {PaidOrders} from './paid-orders.filter';



export default angular.module('filters', [])

.filter('paidOrders', PaidOrders.transform);
new filters.module.js
VIEW CONTROLLERS
old log.controller.js
export function LogController ($scope, $window, Orders, Storage) {



$scope.orders = Orders.getOrders();



$scope.clearHistory = function () {



if ($scope.orders.length === 0) {

return;

}



var result = $window.confirm("Clear History?");

if (result) {

Storage.clear();

$scope.orders = [];

}

}

}
new log.controller.js
export class LogController {



constructor($scope, $window, Orders, Storage) {

$scope.orders = Orders.getOrders();



$scope.clearHistory = function () {



if ($scope.orders.length === 0) {

return;

}



const result = $window.confirm("Clear History?");



if (result) {

Storage.clear();

$scope.orders = [];

}

}

}

}
DROP THE
$SCOPE
MORE JAVASCRIPT LESS ANGULAR
Bind to the controller instance, use setters
for watching changes, free yourself from
$scope events
CLASS SYNTAX
$ git checkout 03_drop_the_scope
old log.controller.js
export class LogController {



constructor($scope, $window, Orders, Storage) {

$scope.orders = Orders.getOrders();



$scope.clearHistory = function () {



if ($scope.orders.length === 0) {

return;

}



const result = $window.confirm("Clear History?");



if (result) {

Storage.clear();

$scope.orders = [];

}

}

}
old routes.js
export function routes($stateProvider, $urlRouterProvider) {



$urlRouterProvider.otherwise("/");



$stateProvider

.state('log', {

url: '/log',

templateUrl: 'templates/log.html',

controller: 'LogController'

})

}
<div class="container-fluid">

<div class="row">

<div class="container-fluid">

<span ng-click="clearHistory()"><i>clear history</i></span>

<br/>

<simple-table orders="orders"></simple-table>

</div>

</div>

</div>
old log.html
new log.controller.js
export class LogController {



constructor( $window, Orders, Storage) {

this.window = $window;

this.store = Storage;

this.orders = Orders.getOrders();

}



clearHistory = function () {



if (this.orders.length === 0) {

return;

}



const result = this.window.confirm("Clear History?");



if (result) {

this.store.clear();

this.orders = [];

}

}

}
new routes.js
export function routes($stateProvider, $urlRouterProvider) {



$urlRouterProvider.otherwise("/");



$stateProvider

.state('log', {

url: '/log',

templateUrl: 'templates/log.html',

controller: ‘LogController as Logs'

})

}
<div class="container-fluid">

<div class="row">

<div class="container-fluid">

<span ng-click="Logs.clearHistory()"><i>clear history</i></span>

<br/>

<simple-table orders="Logs.orders"></simple-table>

</div>

</div>

</div>
new log.html
WATCH CHANGES
$ git checkout 04_watch_for_changes
SHALLOW WATCH?
JUST USE SETTERS.
$ git checkout 05_getters_setters
old home.controller.js
export class HomeController {



constructor(Orders, $scope) {

this.Orders = Orders;

this.menu = this.Orders.getMenuItems();

this.orders = this.Orders.getOrders();

this.selectedOrder = null;



$scope.$watch(()=>this.selectedOrder, this.changeHandler)

}



changeHandler(newVal,oldVal){

console.log('New order Was selected!');

console.log(newVal, oldVal);

}

}
new home.controller.js
export class HomeController {



constructor(Orders) {

this.Orders = Orders;

this.menu = this.Orders.getMenuItems();

this.orders = this.Orders.getOrders();

this._selectedOrder = null;

}



set selectedOrder(order){
this.changeHandler(order);

this._selectedOrder = order; 

}



changeHandler(newVal){

console.log('New order Was selected!');

console.log(newVal);

}

}
DEEP WATCHING?
THINK IMMUTABLE.
$ git checkout 06_be_immutable
old home.controller.js
export class HomeController {



constructor(Orders) {

this.Orders = Orders;

this.menu = this.Orders.getMenuItems();

this.orders = this.Orders.getOrders();

this.selectedOrder = null;

}



createOrder(clientName) {

const order = this.Orders.createOrder(clientName);

this.clientName = '';

this.selectOrder(order);

};
}
new home.controller.js
export class HomeController {



constructor(Orders) {

this.Orders = Orders;

this.menu = this.Orders.getMenuItems();

this._orders = this.Orders.getOrders();

this.selectedOrder = null;

}



set orders(orders) {

console.log('orders changed!', orders);

this._orders = orders;

}



createOrder(clientName) {

const order = this.Orders.createOrder(clientName);

this.orders = this.Orders.getOrders();

this.clientName = '';

this.selectOrder(order);

};
}
EMITTING EVENTS
$ git checkout 07_event_emitter
new dispatcher.js
export class Dispatcher {



constructor() {

this.subjects = {};

}



emit(event, payload){

this.validate(event);

this.subjects[event].forEach( callback => callback.apply(null, payload))

}



on(event, callback){

this.validate(event);

this.subjects[event].push(callback);

}



validate(event){

if(!this.subjects[event]) {

this.subjects[event] = [];

}

}

}
new storage.service.js
export class Storage {



constructor(Dispatcher) {

this.ORDERS_KEY = "ORDERS";

this.store = localStorage;

this.dispatcher = Dispatcher;

}



getOrders() {

return JSON.parse(this.store.getItem(this.ORDERS_KEY)) || [];

};



saveOrders(orders) {

this.store.setItem(this.ORDERS_KEY, JSON.stringify(orders))

this.dispatcher.emit('ORDERS_SAVED', orders);

};



clear() {

this.store.clear();

}

}
new logger.factory.js
export class Logger {



constructor($log, Dispatcher) {

this.$log = $log;

this.timeStamp = new Date().toString();



Dispatcher.on('ORDERS_SAVED', function (data) {

this.debug(`storage saved the orders!`);

console.log(data);

})

}



debug(msg) {

this.$log.debug(this.timeStamp + ": " + msg)

}



log(msg) {

this.$log.log(msg)

}

}
BREAK IT TO
COMPONENTS
COMPOSE COMPONENTS
Break the UI layer into small, maintainable
and reusable building blocks.
HOME
ORDERS LIST ORDER EDITOR
NEW ORDER
FORM
ORDER LIST
ORDER
FORM
NO ORDER
EDIT ORDER
FORM
ORDER ITEM
LIST
EDITOR
FOOTER
PROJECT SRTUCTURE
$ git checkout 08_group_by_feature
old structure new structure
new home.module.js
import {HomeController} from './home.controller';



function routes($stateProvider) {

$stateProvider

.state('home', {

url: '/',

templateUrl: 'home/home.html',

controller: 'HomeController as Home'

})

}



export default angular.module('home', [])

.config(routes)

.controller({HomeController});

DIRECTIVES AS
COMPONENTS
$ git checkout 09_directives_as_components
new folder structure
new home.module.js
function routes($stateProvider) {

$stateProvider

.state('home', {

url: '/',

template: '<home></home>'

})

}



export default angular.module('home', [])

.config(routes)

.filter('paidOrders', PaidOrders.transform)

.directive({

home,

newOrderForm,

orderList,

ordersList,

noSelectedOrder,

editOrderForm,

orderItemList,

orderEditorFooter,

orderEditor

});
new home.js
export function home () {

return {

template: `

<div class="container-fluid">

<div class="row">

<orders-list></orders-list>

<order-editor></order-editor>

</div>

</div>

`,

controller: HomeController,

controllerAs: 'Home'

}

}
new order-list.js
export function ordersList() {

return {

template: `

<div class="col-sm-6">

<new-order-form></new-order-form>

<br/>

<order-list></order-list>

</div>

`

}

}

new order-editor.js
export function orderEditor() {

return {

template: `

<div class="col-sm-6">



<no-selected-order></no-selected-order>



<div class="card" ng-if="Home.selectedOrder">

<div class="card-block">

<edit-order-form></edit-order-form>

<order-item-list></order-item-list>

<order-editor-footer></order-editor-footer>

</div>

</div>

</div>

`

}

}
new no-selected-order.js
export function noSelectedOrder () {

return {

template: `

<div class="card" ng-if="!Home.selectedOrder">

<div class="card-block">

<h4 class="card-title">No order selected.</h4>

</div>

</div>

`

}

}
new order-list-item.js
export function orderItemList () {

return {

template:`

<ul class="list-group list-group-flush">

<li class="list-group-item"

ng-repeat="menuItem in Home.selectedOrder.items">

<span class="label label-default label-pill pull-xs-right">

{{menuItem.itemPrice}}</span>

{{menuItem.itemName}}

</li>

</ul>

`

}

}
FINAL WORDS
MODULAR AND
CLEAN CODE IS
ALWAYS BETTER
MIGRATION
WON’T BE EASY
START WITH
SMALL
IMPORTANT
IMPROVEMENTS
THAT YOU CAN
APPLY TODAY
https://github.com/nirkaufman/ng1-coffee-shop
GRAB THE CODE
http://tinyurl.com/hdmqrem
THANKS
ROME 18-19 MARCH 2016
Nir@500tech.com

@nirkaufman on twitter
slideshare.net/nirkaufman/
github.com/nirkaufman
All pictures belong
to their respective authors

More Related Content

What's hot (20)

PDF
Evan Schultz - Angular Summit - 2016
Evan Schultz
 
PDF
Workshop 13: AngularJS Parte II
Visual Engineering
 
PPTX
AngularJS for Java Developers
Loc Nguyen
 
PDF
AngularJS - Services
Nir Kaufman
 
PDF
Workshop 20: ReactJS Part II Flux Pattern & Redux
Visual Engineering
 
PDF
Modern Web Developement
peychevi
 
PDF
Workshop 22: React-Redux Middleware
Visual Engineering
 
PDF
Creating a WYSIWYG Editor with React
peychevi
 
PDF
Angular js 2.0, ng poznań 20.11
Kamil Augustynowicz
 
PDF
Angular 2.0 - What to expect
Allan Marques Baptista
 
PDF
Building scalable applications with angular js
Andrew Alpert
 
PDF
Workshop 19: ReactJS Introduction
Visual Engineering
 
PDF
Using React, Redux and Saga with Lottoland APIs
Mihail Gaberov
 
PPTX
Angular js 2
Ran Wahle
 
PPTX
Angular2 for Beginners
Oswald Campesato
 
PPTX
ReactJs presentation
nishasowdri
 
PDF
Intro to Redux | DreamLab Academy #3
DreamLab
 
PDF
React lecture
Christoffer Noring
 
PDF
Angular Weekend
Troy Miles
 
PPTX
Migrating an application from Angular 1 to Angular 2
Ross Dederer
 
Evan Schultz - Angular Summit - 2016
Evan Schultz
 
Workshop 13: AngularJS Parte II
Visual Engineering
 
AngularJS for Java Developers
Loc Nguyen
 
AngularJS - Services
Nir Kaufman
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Visual Engineering
 
Modern Web Developement
peychevi
 
Workshop 22: React-Redux Middleware
Visual Engineering
 
Creating a WYSIWYG Editor with React
peychevi
 
Angular js 2.0, ng poznań 20.11
Kamil Augustynowicz
 
Angular 2.0 - What to expect
Allan Marques Baptista
 
Building scalable applications with angular js
Andrew Alpert
 
Workshop 19: ReactJS Introduction
Visual Engineering
 
Using React, Redux and Saga with Lottoland APIs
Mihail Gaberov
 
Angular js 2
Ran Wahle
 
Angular2 for Beginners
Oswald Campesato
 
ReactJs presentation
nishasowdri
 
Intro to Redux | DreamLab Academy #3
DreamLab
 
React lecture
Christoffer Noring
 
Angular Weekend
Troy Miles
 
Migrating an application from Angular 1 to Angular 2
Ross Dederer
 

Viewers also liked (20)

PDF
Angular2 - getting-ready
Nir Kaufman
 
PDF
Angular2 workshop
Nir Kaufman
 
PDF
Angular Pipes Workshop
Nir Kaufman
 
PDF
Getting Started with Angular 2
FITC
 
PDF
Solid angular
Nir Kaufman
 
PDF
Angularjs - Unit testing introduction
Nir Kaufman
 
PDF
Angular 2 overview
Jesse Warden
 
PPTX
Angular 2 - Better or worse
Vladimir Georgiev
 
PDF
Angular 2 - Core Concepts
Fabio Biondi
 
ODP
Introduction to Angular 2
Knoldus Inc.
 
PDF
Building Universal Applications with Angular 2
Minko Gechev
 
PDF
Data Structures in javaScript 2015
Nir Kaufman
 
PDF
redux and angular - up and running
Nir Kaufman
 
PDF
Up & running with ECMAScript6
Nir Kaufman
 
PDF
Adventures with Angular 2
Dragos Ionita
 
PDF
Webstorm
Nir Kaufman
 
PDF
Angularjs - lazy loading techniques
Nir Kaufman
 
PPTX
Angular2 inter3
Oswald Campesato
 
PDF
Webpack and angularjs
Nir Kaufman
 
Angular2 - getting-ready
Nir Kaufman
 
Angular2 workshop
Nir Kaufman
 
Angular Pipes Workshop
Nir Kaufman
 
Getting Started with Angular 2
FITC
 
Solid angular
Nir Kaufman
 
Angularjs - Unit testing introduction
Nir Kaufman
 
Angular 2 overview
Jesse Warden
 
Angular 2 - Better or worse
Vladimir Georgiev
 
Angular 2 - Core Concepts
Fabio Biondi
 
Introduction to Angular 2
Knoldus Inc.
 
Building Universal Applications with Angular 2
Minko Gechev
 
Data Structures in javaScript 2015
Nir Kaufman
 
redux and angular - up and running
Nir Kaufman
 
Up & running with ECMAScript6
Nir Kaufman
 
Adventures with Angular 2
Dragos Ionita
 
Webstorm
Nir Kaufman
 
Angularjs - lazy loading techniques
Nir Kaufman
 
Angular2 inter3
Oswald Campesato
 
Webpack and angularjs
Nir Kaufman
 
Ad

Similar to How Angular2 Can Improve Your AngularJS Apps Today! (20)

PPTX
Angular Workshop_Sarajevo2
Christoffer Noring
 
PPTX
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
Learnimtactics
 
PDF
Angular.js is super cool
Maksym Hopei
 
PDF
Introduction to AngularJS
Jussi Pohjolainen
 
PPTX
Angular js for enteprise application
vu van quyet
 
PPTX
Working with AngularJS
André Vala
 
PPTX
Intoduction to Angularjs
Gaurav Agrawal
 
PDF
Leveling up with AngularJS
Austin Condiff
 
PPTX
01 startoff angularjs
Erhwen Kuo
 
PDF
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Alessandro Nadalin
 
DOCX
Angular js
prasaddammalapati
 
PPTX
Angular Presentation
Adam Moore
 
PDF
Angular js is the future. maybe. @ ConFoo 2014 in Montreal (CA)
Alessandro Nadalin
 
PPTX
Introduction to Angular JS
Santhosh Kumar Srinivasan
 
PDF
AngularJS Basics
Ravi Mone
 
PDF
AngularJS Curriculum-Zeolearn
Hamdi Ceylan
 
PPTX
Migrating From Angular 1.x to Angular 2+
Asim Hussain
 
PPTX
Angular js
Mauro Servienti
 
PPTX
Introduction to Angular js 2.0
Nagaraju Sangam
 
PDF
AngularJS 101
Houssem Yahiaoui
 
Angular Workshop_Sarajevo2
Christoffer Noring
 
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
Learnimtactics
 
Angular.js is super cool
Maksym Hopei
 
Introduction to AngularJS
Jussi Pohjolainen
 
Angular js for enteprise application
vu van quyet
 
Working with AngularJS
André Vala
 
Intoduction to Angularjs
Gaurav Agrawal
 
Leveling up with AngularJS
Austin Condiff
 
01 startoff angularjs
Erhwen Kuo
 
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Alessandro Nadalin
 
Angular js
prasaddammalapati
 
Angular Presentation
Adam Moore
 
Angular js is the future. maybe. @ ConFoo 2014 in Montreal (CA)
Alessandro Nadalin
 
Introduction to Angular JS
Santhosh Kumar Srinivasan
 
AngularJS Basics
Ravi Mone
 
AngularJS Curriculum-Zeolearn
Hamdi Ceylan
 
Migrating From Angular 1.x to Angular 2+
Asim Hussain
 
Angular js
Mauro Servienti
 
Introduction to Angular js 2.0
Nagaraju Sangam
 
AngularJS 101
Houssem Yahiaoui
 
Ad

More from Nir Kaufman (13)

PDF
Angular Dependency Injection
Nir Kaufman
 
PDF
Angular Prestige: Less-known API and techniques
Nir Kaufman
 
PDF
Angular CLI custom builders
Nir Kaufman
 
PDF
Electronic music 101 for developers
Nir Kaufman
 
PDF
Nestjs MasterClass Slides
Nir Kaufman
 
PDF
Angular EE - Special Workshop by Nir Kaufman
Nir Kaufman
 
PDF
Decorators in js
Nir Kaufman
 
PDF
Styling recipes for Angular components
Nir Kaufman
 
PDF
Introduction To Angular's reactive forms
Nir Kaufman
 
PDF
Angular redux
Nir Kaufman
 
PDF
AngularJS performance & production tips
Nir Kaufman
 
PDF
Angular js - 10 reasons to choose angularjs
Nir Kaufman
 
PDF
Angular js routing options
Nir Kaufman
 
Angular Dependency Injection
Nir Kaufman
 
Angular Prestige: Less-known API and techniques
Nir Kaufman
 
Angular CLI custom builders
Nir Kaufman
 
Electronic music 101 for developers
Nir Kaufman
 
Nestjs MasterClass Slides
Nir Kaufman
 
Angular EE - Special Workshop by Nir Kaufman
Nir Kaufman
 
Decorators in js
Nir Kaufman
 
Styling recipes for Angular components
Nir Kaufman
 
Introduction To Angular's reactive forms
Nir Kaufman
 
Angular redux
Nir Kaufman
 
AngularJS performance & production tips
Nir Kaufman
 
Angular js - 10 reasons to choose angularjs
Nir Kaufman
 
Angular js routing options
Nir Kaufman
 

Recently uploaded (20)

PDF
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
PDF
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
PPTX
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
PDF
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
PPTX
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
PDF
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PPTX
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
“Computer Vision at Sea: Automated Fish Tracking for Sustainable Fishing,” a ...
Edge AI and Vision Alliance
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 

How Angular2 Can Improve Your AngularJS Apps Today!

  • 1. HOW ANGULAR2 CAN IMPROVE YOUR ANGULARJS APPS TODAY! Nir Kaufman
  • 2. NIR KUFMN Nir Kaufman - Doing Angular for years - Wrote a book about Angular2 - Play the electric Bass Head of Angular Development @ 500Tech *This picture have been retouched the actual speaker may look different
  • 6. I AM NOT GOING TO TALK ABOUT - TypeScript - Angular2 upgrade module - Ng-forward library - Data flow (Redux, RxJs) - Angular 1.5 new Component API
  • 8. GET READY FOR THE MIGRATION
  • 14. IT WILL IMPROVE YOUR APP DESIGN
  • 15. AND GET YOU READY FOR THE FUTURE
  • 17. I WILL TALK ABOUT - Embracing Modules - Using Classes - Decoupling from Framework API - Components as UI building blocks
  • 22. THAT YOU CAN COMPLETE IN ONE SPRINT
  • 26. EVERYTHING IS A MODULE $ git checkout 01_modules
  • 27. USE A MODULE LOADER Integrate a module bundler and an ES6 compiler to use javaScript modules. http://webpack.github.io/
  • 29. module.exports = {
 entry: 'index.js',
 
 // configure loaders
 module: {
 loaders: [
 {
 test: /.js$/,
 exclude: /node_modules/,
 loader: "babel",
 query: {presets: ['es2015', 'stage-1']}
 },
 
 // load css as inline styles
 {test: /.css$/, loader: "style!css"}
 ]
 }
 }; new webpack.config.js
  • 30. <script src="bundle.js"></script> old index.html <!-- load core scripts -->
 <script src="../node_modules/angular/angular.js"></script>
 <script src="../node_modules/angular-ui-router/release/angular-ui- router.js"></script>
 <script src="index.js"></script>
 
 <!-- load services -->
 <script src="services/logger.factory.js"></script>
 <script src="services/storage.service.js"></script>
 <script src="services/orders.service.js"></script>
 
 <!-- load filters -->
 <script src="filters/paid-orders.filter.js"></script>
 
 <!-- load directives -->
 <script src="directives/simple-table/simple-table.js"></script>
 
 <!-- load controllers -->
 <script src="states/home.controller.js"></script>
 <script src="states/log.controller.js"></script>
  • 31. <body> <script src=“bundle.js"></script> </body> new index.html import 'angular';
 import 'angular-ui-router';
 import './assets/index.css';
 
 
 import services from './services/services.module';
 import filters from './filters/filters.module'
 import directives from './directives/directives.module';
 import states from './states/state.module'; new index.js
  • 33. old log.controller.js (function (angular) {
 
 angular.module('app')
 .controller('LogController', function ($scope, $window, Orders, Storage) {
 $scope.orders = Orders.getOrders();
 
 $scope.clearHistory = function () {
 
 if ($scope.orders.length === 0) {
 return;
 }
 
 var result = $window.confirm("Clear History?");
 if (result) {
 Storage.clear();
 $scope.orders = [];
 }
 }
 })
 
 }(window.angular));
  • 34. new log.controller.js export function LogController ($scope, $window, Orders, Storage) {
 
 $scope.orders = Orders.getOrders();
 
 $scope.clearHistory = function () {
 
 if ($scope.orders.length === 0) {
 return;
 }
 
 var result = $window.confirm("Clear History?");
 if (result) {
 Storage.clear();
 $scope.orders = [];
 }
 }
 }
  • 36. old storage.service.js (function (angular) { 
 angular.module('app')
 .service('Storage', function () {
 
 var ORDERS_KEY = "ORDERS";
 this.store = localStorage;
 
 this.getOrders = function () {
 return JSON.parse(this.store.getItem(ORDERS_KEY)) || [];
 };
 
 this.saveOrders = function (orders) {
 this.store.setItem(ORDERS_KEY, JSON.stringify(orders))
 };
 
 this.clear = function () {
 this.store.clear();
 }
 }) 
 }(window.angular));
  • 37. new storage.service.js export function Storage () {
 
 var ORDERS_KEY = "ORDERS";
 this.store = localStorage;
 
 this.getOrders = function () {
 return JSON.parse(this.store.getItem(ORDERS_KEY)) || [];
 };
 
 this.saveOrders = function (orders) {
 this.store.setItem(ORDERS_KEY, JSON.stringify(orders))
 };
 } import {Storage} from './storage.service';
 
 export default angular.module('services', [])
 .service('Storage', Storage) new service.module.js
  • 38. old index.js (function (angular) {
 
 angular.module('app', ['ui.router'])
 .config(function ($stateProvider, $urlRouterProvider) {
 
 $urlRouterProvider.otherwise("/");
 
 $stateProvider
 .state('home', {
 url: '/',
 templateUrl: 'templates/home.html',
 controller: 'HomeController'
 })
 .state('log', {
 url: '/log',
 templateUrl: 'templates/log.html',
 controller: 'LogController'
 })
 }); 
 }(window.angular)
  • 39. new index.js import 'angular';
 import 'angular-ui-router';
 import ‘./assets/index.css'; 
 import services from './services/services.module';
 import filters from './filters/filters.module'
 import directives from './directives/directives.module';
 import states from './states/state.module';
 import {routes} from './config/routes';
 
 angular.module('app', [
 'ui.router',
 services.name,
 directives.name,
 filters.name,
 states.name ]).config(routes);
 
 // bootstrap angular
 angular.element(document).ready(function () {
 angular.bootstrap(document, ['app']);
 });
  • 40. new routes.js export function routes($stateProvider, $urlRouterProvider) {
 
 $urlRouterProvider.otherwise("/");
 
 // configure application routes
 $stateProvider
 .state('home', {
 url: '/',
 templateUrl: 'templates/home.html',
 controller: 'HomeController'
 })
 
 .state('log', {
 url: '/log',
 templateUrl: 'templates/log.html',
 controller: 'LogController'
 })
 }
  • 41. EVERYTHING IS A CLASS $ git checkout 02_classes
  • 42. MOVE FORWARD TO ES6 You can adopt the new syntax slowly. Start by using classes instead of functions. http://babeljs.io/
  • 44. old storage.service.js export function Storage () {
 
 var ORDERS_KEY = "ORDERS";
 this.store = localStorage;
 
 this.getOrders = function () {
 return JSON.parse(this.store.getItem(ORDERS_KEY)) || [];
 };
 
 this.saveOrders = function (orders) {
 this.store.setItem(ORDERS_KEY, JSON.stringify(orders))
 };
 }
  • 45. new storage.service.js export class Storage {
 
 constructor() {
 this.ORDERS_KEY = "ORDERS";
 this.store = localStorage;
 }
 
 getOrders() {
 return JSON.parse(this.store.getItem(this.ORDERS_KEY)) || [];
 };
 
 saveOrders(orders) {
 this.store.setItem(this.ORDERS_KEY, JSON.stringify(orders))
 };
 }
  • 47. old paid-orders.filter.js export function paidOrders() { 
 return function (orders) {
 return orders.filter(order => order.paid === false)
 } 
 } import {paidOrders} from './paid-orders.filter';
 
 export default angular.module('filters', [])
 .filter('paidOrders',paidOrders); old filters.module.js
  • 48. new paid-orders.filter.js export class PaidOrders {
 
 static transform () {
 return (orders) => orders.filter(order => order.paid === false)
 }
 } import {PaidOrders} from './paid-orders.filter';
 
 export default angular.module('filters', [])
 .filter('paidOrders', PaidOrders.transform); new filters.module.js
  • 50. old log.controller.js export function LogController ($scope, $window, Orders, Storage) {
 
 $scope.orders = Orders.getOrders();
 
 $scope.clearHistory = function () {
 
 if ($scope.orders.length === 0) {
 return;
 }
 
 var result = $window.confirm("Clear History?");
 if (result) {
 Storage.clear();
 $scope.orders = [];
 }
 }
 }
  • 51. new log.controller.js export class LogController {
 
 constructor($scope, $window, Orders, Storage) {
 $scope.orders = Orders.getOrders();
 
 $scope.clearHistory = function () {
 
 if ($scope.orders.length === 0) {
 return;
 }
 
 const result = $window.confirm("Clear History?");
 
 if (result) {
 Storage.clear();
 $scope.orders = [];
 }
 }
 }
 }
  • 53. MORE JAVASCRIPT LESS ANGULAR Bind to the controller instance, use setters for watching changes, free yourself from $scope events
  • 54. CLASS SYNTAX $ git checkout 03_drop_the_scope
  • 55. old log.controller.js export class LogController {
 
 constructor($scope, $window, Orders, Storage) {
 $scope.orders = Orders.getOrders();
 
 $scope.clearHistory = function () {
 
 if ($scope.orders.length === 0) {
 return;
 }
 
 const result = $window.confirm("Clear History?");
 
 if (result) {
 Storage.clear();
 $scope.orders = [];
 }
 }
 }
  • 56. old routes.js export function routes($stateProvider, $urlRouterProvider) {
 
 $urlRouterProvider.otherwise("/");
 
 $stateProvider
 .state('log', {
 url: '/log',
 templateUrl: 'templates/log.html',
 controller: 'LogController'
 })
 } <div class="container-fluid">
 <div class="row">
 <div class="container-fluid">
 <span ng-click="clearHistory()"><i>clear history</i></span>
 <br/>
 <simple-table orders="orders"></simple-table>
 </div>
 </div>
 </div> old log.html
  • 57. new log.controller.js export class LogController {
 
 constructor( $window, Orders, Storage) {
 this.window = $window;
 this.store = Storage;
 this.orders = Orders.getOrders();
 }
 
 clearHistory = function () {
 
 if (this.orders.length === 0) {
 return;
 }
 
 const result = this.window.confirm("Clear History?");
 
 if (result) {
 this.store.clear();
 this.orders = [];
 }
 }
 }
  • 58. new routes.js export function routes($stateProvider, $urlRouterProvider) {
 
 $urlRouterProvider.otherwise("/");
 
 $stateProvider
 .state('log', {
 url: '/log',
 templateUrl: 'templates/log.html',
 controller: ‘LogController as Logs'
 })
 } <div class="container-fluid">
 <div class="row">
 <div class="container-fluid">
 <span ng-click="Logs.clearHistory()"><i>clear history</i></span>
 <br/>
 <simple-table orders="Logs.orders"></simple-table>
 </div>
 </div>
 </div> new log.html
  • 59. WATCH CHANGES $ git checkout 04_watch_for_changes
  • 60. SHALLOW WATCH? JUST USE SETTERS. $ git checkout 05_getters_setters
  • 61. old home.controller.js export class HomeController {
 
 constructor(Orders, $scope) {
 this.Orders = Orders;
 this.menu = this.Orders.getMenuItems();
 this.orders = this.Orders.getOrders();
 this.selectedOrder = null;
 
 $scope.$watch(()=>this.selectedOrder, this.changeHandler)
 }
 
 changeHandler(newVal,oldVal){
 console.log('New order Was selected!');
 console.log(newVal, oldVal);
 }
 }
  • 62. new home.controller.js export class HomeController {
 
 constructor(Orders) {
 this.Orders = Orders;
 this.menu = this.Orders.getMenuItems();
 this.orders = this.Orders.getOrders();
 this._selectedOrder = null;
 }
 
 set selectedOrder(order){ this.changeHandler(order);
 this._selectedOrder = order; 
 }
 
 changeHandler(newVal){
 console.log('New order Was selected!');
 console.log(newVal);
 }
 }
  • 63. DEEP WATCHING? THINK IMMUTABLE. $ git checkout 06_be_immutable
  • 64. old home.controller.js export class HomeController {
 
 constructor(Orders) {
 this.Orders = Orders;
 this.menu = this.Orders.getMenuItems();
 this.orders = this.Orders.getOrders();
 this.selectedOrder = null;
 }
 
 createOrder(clientName) {
 const order = this.Orders.createOrder(clientName);
 this.clientName = '';
 this.selectOrder(order);
 }; }
  • 65. new home.controller.js export class HomeController {
 
 constructor(Orders) {
 this.Orders = Orders;
 this.menu = this.Orders.getMenuItems();
 this._orders = this.Orders.getOrders();
 this.selectedOrder = null;
 }
 
 set orders(orders) {
 console.log('orders changed!', orders);
 this._orders = orders;
 }
 
 createOrder(clientName) {
 const order = this.Orders.createOrder(clientName);
 this.orders = this.Orders.getOrders();
 this.clientName = '';
 this.selectOrder(order);
 }; }
  • 66. EMITTING EVENTS $ git checkout 07_event_emitter
  • 67. new dispatcher.js export class Dispatcher {
 
 constructor() {
 this.subjects = {};
 }
 
 emit(event, payload){
 this.validate(event);
 this.subjects[event].forEach( callback => callback.apply(null, payload))
 }
 
 on(event, callback){
 this.validate(event);
 this.subjects[event].push(callback);
 }
 
 validate(event){
 if(!this.subjects[event]) {
 this.subjects[event] = [];
 }
 }
 }
  • 68. new storage.service.js export class Storage {
 
 constructor(Dispatcher) {
 this.ORDERS_KEY = "ORDERS";
 this.store = localStorage;
 this.dispatcher = Dispatcher;
 }
 
 getOrders() {
 return JSON.parse(this.store.getItem(this.ORDERS_KEY)) || [];
 };
 
 saveOrders(orders) {
 this.store.setItem(this.ORDERS_KEY, JSON.stringify(orders))
 this.dispatcher.emit('ORDERS_SAVED', orders);
 };
 
 clear() {
 this.store.clear();
 }
 }
  • 69. new logger.factory.js export class Logger {
 
 constructor($log, Dispatcher) {
 this.$log = $log;
 this.timeStamp = new Date().toString();
 
 Dispatcher.on('ORDERS_SAVED', function (data) {
 this.debug(`storage saved the orders!`);
 console.log(data);
 })
 }
 
 debug(msg) {
 this.$log.debug(this.timeStamp + ": " + msg)
 }
 
 log(msg) {
 this.$log.log(msg)
 }
 }
  • 71. COMPOSE COMPONENTS Break the UI layer into small, maintainable and reusable building blocks.
  • 72. HOME ORDERS LIST ORDER EDITOR NEW ORDER FORM ORDER LIST ORDER FORM NO ORDER EDIT ORDER FORM ORDER ITEM LIST EDITOR FOOTER
  • 73. PROJECT SRTUCTURE $ git checkout 08_group_by_feature
  • 74. old structure new structure
  • 75. new home.module.js import {HomeController} from './home.controller';
 
 function routes($stateProvider) {
 $stateProvider
 .state('home', {
 url: '/',
 templateUrl: 'home/home.html',
 controller: 'HomeController as Home'
 })
 }
 
 export default angular.module('home', [])
 .config(routes)
 .controller({HomeController});

  • 76. DIRECTIVES AS COMPONENTS $ git checkout 09_directives_as_components
  • 78. new home.module.js function routes($stateProvider) {
 $stateProvider
 .state('home', {
 url: '/',
 template: '<home></home>'
 })
 }
 
 export default angular.module('home', [])
 .config(routes)
 .filter('paidOrders', PaidOrders.transform)
 .directive({
 home,
 newOrderForm,
 orderList,
 ordersList,
 noSelectedOrder,
 editOrderForm,
 orderItemList,
 orderEditorFooter,
 orderEditor
 });
  • 79. new home.js export function home () {
 return {
 template: `
 <div class="container-fluid">
 <div class="row">
 <orders-list></orders-list>
 <order-editor></order-editor>
 </div>
 </div>
 `,
 controller: HomeController,
 controllerAs: 'Home'
 }
 }
  • 80. new order-list.js export function ordersList() {
 return {
 template: `
 <div class="col-sm-6">
 <new-order-form></new-order-form>
 <br/>
 <order-list></order-list>
 </div>
 `
 }
 }

  • 81. new order-editor.js export function orderEditor() {
 return {
 template: `
 <div class="col-sm-6">
 
 <no-selected-order></no-selected-order>
 
 <div class="card" ng-if="Home.selectedOrder">
 <div class="card-block">
 <edit-order-form></edit-order-form>
 <order-item-list></order-item-list>
 <order-editor-footer></order-editor-footer>
 </div>
 </div>
 </div>
 `
 }
 }
  • 82. new no-selected-order.js export function noSelectedOrder () {
 return {
 template: `
 <div class="card" ng-if="!Home.selectedOrder">
 <div class="card-block">
 <h4 class="card-title">No order selected.</h4>
 </div>
 </div>
 `
 }
 }
  • 83. new order-list-item.js export function orderItemList () {
 return {
 template:`
 <ul class="list-group list-group-flush">
 <li class="list-group-item"
 ng-repeat="menuItem in Home.selectedOrder.items">
 <span class="label label-default label-pill pull-xs-right">
 {{menuItem.itemPrice}}</span>
 {{menuItem.itemName}}
 </li>
 </ul>
 `
 }
 }
  • 85. MODULAR AND CLEAN CODE IS ALWAYS BETTER
  • 90. THANKS ROME 18-19 MARCH 2016 [email protected]
 @nirkaufman on twitter slideshare.net/nirkaufman/ github.com/nirkaufman All pictures belong to their respective authors