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

PDF
Boosting Angular runtime performance
PDF
Redux with angular 2 - workshop 2016
PDF
An introduction to Angular2
PDF
Angular2 & ngrx/store: Game of States
PDF
Evan Schultz - Angular Camp - ng2-redux
PDF
Workshop 14: AngularJS Parte III
PDF
Redux pattens - JSHeroes 2018
PDF
Reactive.architecture.with.Angular
Boosting Angular runtime performance
Redux with angular 2 - workshop 2016
An introduction to Angular2
Angular2 & ngrx/store: Game of States
Evan Schultz - Angular Camp - ng2-redux
Workshop 14: AngularJS Parte III
Redux pattens - JSHeroes 2018
Reactive.architecture.with.Angular

What's hot (20)

PDF
Evan Schultz - Angular Summit - 2016
PDF
Workshop 13: AngularJS Parte II
PPTX
AngularJS for Java Developers
PDF
AngularJS - Services
PDF
Workshop 20: ReactJS Part II Flux Pattern & Redux
PDF
Modern Web Developement
PDF
Workshop 22: React-Redux Middleware
PDF
Creating a WYSIWYG Editor with React
PDF
Angular js 2.0, ng poznań 20.11
PDF
Angular 2.0 - What to expect
PDF
Building scalable applications with angular js
PDF
Workshop 19: ReactJS Introduction
PDF
Using React, Redux and Saga with Lottoland APIs
PPTX
Angular js 2
PPTX
Angular2 for Beginners
PPTX
ReactJs presentation
PDF
Intro to Redux | DreamLab Academy #3
PDF
React lecture
PDF
Angular Weekend
PPTX
Migrating an application from Angular 1 to Angular 2
Evan Schultz - Angular Summit - 2016
Workshop 13: AngularJS Parte II
AngularJS for Java Developers
AngularJS - Services
Workshop 20: ReactJS Part II Flux Pattern & Redux
Modern Web Developement
Workshop 22: React-Redux Middleware
Creating a WYSIWYG Editor with React
Angular js 2.0, ng poznań 20.11
Angular 2.0 - What to expect
Building scalable applications with angular js
Workshop 19: ReactJS Introduction
Using React, Redux and Saga with Lottoland APIs
Angular js 2
Angular2 for Beginners
ReactJs presentation
Intro to Redux | DreamLab Academy #3
React lecture
Angular Weekend
Migrating an application from Angular 1 to Angular 2
Ad

Viewers also liked (20)

PDF
Angular2 - getting-ready
PDF
Angular2 workshop
PDF
Angular Pipes Workshop
PDF
Getting Started with Angular 2
PDF
Solid angular
PDF
Angularjs - Unit testing introduction
PDF
Angular 2 overview
PPTX
Angular 2 - Better or worse
PDF
Angular 2 - Core Concepts
ODP
Introduction to Angular 2
PDF
Building Universal Applications with Angular 2
PDF
Data Structures in javaScript 2015
PDF
redux and angular - up and running
PDF
Up & running with ECMAScript6
PDF
Adventures with Angular 2
PDF
Webstorm
PDF
Angularjs - lazy loading techniques
PPTX
Angular2 inter3
PDF
Webpack and angularjs
Angular2 - getting-ready
Angular2 workshop
Angular Pipes Workshop
Getting Started with Angular 2
Solid angular
Angularjs - Unit testing introduction
Angular 2 overview
Angular 2 - Better or worse
Angular 2 - Core Concepts
Introduction to Angular 2
Building Universal Applications with Angular 2
Data Structures in javaScript 2015
redux and angular - up and running
Up & running with ECMAScript6
Adventures with Angular 2
Webstorm
Angularjs - lazy loading techniques
Angular2 inter3
Webpack and angularjs
Ad

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

PDF
Ultimate Introduction To AngularJS
PDF
AngularJs
PPT
MEAN - Notes from the field (Full-Stack Development with Javascript)
PPT
AngularJS Testing Strategies
PPTX
Building an End-to-End AngularJS Application
PDF
Min-Maxing Software Costs
PPTX
Angular Workshop_Sarajevo2
PDF
CFCouchbase 2.0 and N1QL
PDF
Cf Couchbase 2.0-and-N1-QL
PDF
Introduction to Zend Framework web services
PPTX
AngularJS.part1
KEY
Zend framework service
KEY
Zend framework service
PDF
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
PDF
Bonnes pratiques de développement avec Node js
PPTX
AngularJS, More Than Directives !
PDF
JavaScript Fundamentals with Angular and Lodash
PDF
Inversion Of Control
PDF
Understanding backbonejs
PPT
Coffee@DBG - Exploring Angular JS
Ultimate Introduction To AngularJS
AngularJs
MEAN - Notes from the field (Full-Stack Development with Javascript)
AngularJS Testing Strategies
Building an End-to-End AngularJS Application
Min-Maxing Software Costs
Angular Workshop_Sarajevo2
CFCouchbase 2.0 and N1QL
Cf Couchbase 2.0-and-N1-QL
Introduction to Zend Framework web services
AngularJS.part1
Zend framework service
Zend framework service
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
Bonnes pratiques de développement avec Node js
AngularJS, More Than Directives !
JavaScript Fundamentals with Angular and Lodash
Inversion Of Control
Understanding backbonejs
Coffee@DBG - Exploring Angular JS

More from Nir Kaufman (13)

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

Recently uploaded (20)

PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Empathic Computing: Creating Shared Understanding
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
Big Data Technologies - Introduction.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
[발표본] 너의 과제는 클라우드에 있어_KTDS_김동현_20250524.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Modernizing your data center with Dell and AMD
PDF
KodekX | Application Modernization Development
PPTX
Understanding_Digital_Forensics_Presentation.pptx
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Empathic Computing: Creating Shared Understanding
Unlocking AI with Model Context Protocol (MCP)
20250228 LYD VKU AI Blended-Learning.pptx
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Big Data Technologies - Introduction.pptx
Approach and Philosophy of On baking technology
Dropbox Q2 2025 Financial Results & Investor Presentation
NewMind AI Weekly Chronicles - August'25 Week I
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
[발표본] 너의 과제는 클라우드에 있어_KTDS_김동현_20250524.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Per capita expenditure prediction using model stacking based on satellite ima...
Reach Out and Touch Someone: Haptics and Empathic Computing
Modernizing your data center with Dell and AMD
KodekX | Application Modernization Development
Understanding_Digital_Forensics_Presentation.pptx

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