Get ready folks!
I'm Sajeetharan Sinnathurai
@kokkisajee
ng-Hello!
In a nutshell
Communities
Social Developer
Recognitions
If you don't know what to do
Stop ....Breathe ....
Then
Now
Why Angular?
Angular as a Framework
Why Angular?
Angular as a Platform
Why Angular?
Angular As an Ecosystem
Hero No 1 of the day
AngularX has been reimplemented, not an evolution of Angularjs
Component based UI
$scope
ng-if
ng-app
ng-model
mobile
oriented
better
performance
x7
Languages
ES5
ES6
You can use any language that transpiles your code to Javascript, but I recommend using TypeScript
Advantages
{
export class EntrenadorPokemon {
private nombre:string;
private pokeballs:number;
constructor(nombre: string,
pokeballs: number) {
this.nombre = nombre;
this.pokeballs = pokeballs;
}
getNombre() {
return this.nombre;
}
toString() {
return "Nombre: "+ this.nombre +
", Pokeballs: " + this.pokeballs;
}
}
function EntrenadorPokemon(nombre, pokeballs) {
this.nombre = nombre;
this.pokeballs = pokeballs;
}
EntrenadorPokemon.prototype.getNombre =
function(){
return this.nombre;
};
EntrenadorPokemon.prototype.toString =
function(){
return "Nombre: "+ this.nombre +
", Pokeballs: " + this. pokeballs;
};
ES5
TypeScript
VS
Class
import { EntrenadorPokemon } from "./EntrenadorPokemon";
let entrenadores = new Array<EntrenadorPokemon>();
entrenadores.push(new EntrenadorPokemon('Ash', 150);
entrenadores.push(new EntrenadorPokemon('Josh', 30);
for(let entrenador of entrenadores) {
console.log(entrenador.getNombre());
}
entrenadores.forEach(entrenador => {
console.log(entrenador);
});
Imports
import { EntrenadorPokemon } from "./EntrenadorPokemon";
let entrenadores = new Array<EntrenadorPokemon>();
entrenadores.push(new EntrenadorPokemon('Ash', 150);
entrenadores.push(new EntrenadorPokemon('Josh', 30);
for(let entrenador of entrenadores) {
console.log(entrenador.getNombre());
}
entrenadores.forEach(entrenador => {
console.log(entrenador);
});
Variables
Get & Set
class Goomba {
private life: number;
get life(): number {
return this.life;
}
set life(hearts: number) {
this.life = hearts;
}
}
how to use it
let enemy = new Goomba();
if(enemy.life == 0) {
console.log('Goomba KO');
enemy.life = 100;
}
Definition Attributes
class Goomba {
private life: number;
constructor(hearts: number) {
this.life = hearts;
}
}
class Goomba {
constructor(private life: number) {
...
}
}
World
1-1
x
1
CLI. What is it?
ngular
Scaffold
Preview
Local build
Local Testing
Unit tests
E2E tests
CLI vs WebPack?
ngular
. Wraps Webpack
. Simple to configure
. Handy commands for generating classes, components …
. Cannot do advance configurations
. A bit slow
.Details configuration
.Faster and customizable
.Less buggy
.Understand workflow better
.For curios/expert users
.A lot of stuff to manage
building blocks
ngular
"Mathews is a Poor Captain,Runner of SriLanka in the Decade"
Module
Component
Pipes
Directives
Metadata
Services
Dependency Injection
Component
import { Component } from '@angular/core';
@Component({
selector: 'world', // Name of the html tag
providers: [], // Services
styleUrls: [], // Url of the styles
templateUrl: './world.component.html'
})
export class WorldComponent {
}
ngular
Basic building block of an UI in an Angular application
Module
Angular has at least one module, either root or functionality, it's a class with a decorator @ngModule
Highest level of abstraction
ngular
How are the components organized?
ngular
Module
Directive
Structure
Attribute
<li *ngFor="let enemy of enemies">
</li>
<enemy *ngIf="hasLife">
</enemy>
*ngFor
*ngIf
<div [ngClass]="['bold-text', 'green']"></div>
<div [ngClass]="'italic-text blue'"></div>
<div [ngClass]="{'small-text': true, 'red': true}"></div>
ngClass
ngStyle
You can create your own!
No more ng-show, ng-hide, ng-click but functionality is still available
...
...
ngular
ngular
Services
There is a single object of each service in the application (singleton)
That is, all the components share "the same" service
In this way the services maintain the status of the application
ngular
Services
You can make a service not shared among all the components of the application (not singleton)
You can create an exclusive service for a component and its children
Instead of declaring the service in @NgModule providers it is declared in the @Component
It can be shared by the parent component and by its children components (included in it)
import { Injectable } from '@angular/core';
@Injectable()
export class BlockService {
getCoins() {
return 100;
}
}
ngular
Services
ngular
import { Pipe } from '@angular/core';
import { PipeTransform } from '@angular/core';
@Pipe({name: 'filterReviewByStatus'})
export class FilterReviewByStatusPipe implements PipeTransform {
}
Pipes
Exclusive service for a component
import { Component } from '@angular/core';
import { BlockCoins } from './blockCoins.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
providers: 'BlockCoins'
})
export class AppComponent {
constructor (private blockCoins: BlockCoins) {
}
}
ngular
Services
Exclusive service for a component
export class AppComponent {
constructor (private blockCoins: BlockCoins) {
}
}
ngular
DI
Dependency Injection is a design pattern that passes an object as dependencies in different components across the application.
It creates a new instance of class along with its required dependencies
ngular
Life Cycle
Events
<button (click)="jump()"></button>
ngular
Attributes
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
name = 'Mario';
imageUrl = 'assets/img/mario.png';
}
ngular
<h1>It is me {{name}}</h1>
<img [src]="imgUrl"/>
app.component.html
app.component.ts
Data Binding
DOM
Component
{{ value }}
[property] = *value*
(event) = *handler*
[(event)] = *handler*
ngular
Comunication
ngular
Configuration of Properties (Father -> Son)
<world [name]="worldName"></world>
export class AppComponent {
worldName = 'World 1-1';
}
import {Component, Input} from '@angular/core';
export class WorldComponent {
@Input()
private name: string;
}
<h1>{{name}}</h1>
app.component.ts
app.component.html
world.component.ts
world.component.html
Sending Events ( Son -> Father)
<world [name]="worldName" (changeName)='changeWorld($event)'></world>
export class AppComponent {
worldName:string = 'World 1-1';
changeWorld(name: string) {
this.worldName = name;
}
}
import {Component, Input, Output, EventEmitter} from '@angular/core';
export class WorldComponent {
@Input()
private name: string;
@Output()
changeName = new EventEmitter<string>();
click(level) {
this.changeName.next(level);
}
}
<h1>{{name}}</h1>
<button (click)='click("World 1-2")'>Next level</button>
app.component.ts
app.component.html
world.component.ts
world.component.html
Comunication
ngular
Router
ngular
<router-outlet></router-outlet>
<a [routerLink]="/world1"></a>
Set the Route
This is the container where the component or module indicated by the router will be loaded
World
2-1
x
2
Architecture
ngular
Architecture
ngular
Our application is divided in two parts. -Application itself & Application bootstrap
Our modules, routes, components & services live here.
We bootstrap our app depending on what platform were developing for, and add any required polyfills & vendors.
Typescript config, npm packages, scripts, webpack config, express server, and so on...
World
3-1
x
3
Download
Install
Run!
https://nodejs.org/en/download/
npm install -g @angular/cli@latest
ng new ngHero --routing --style=scss
cd ngHero
npm start
We are going to create these elements in Angular
Let's make something awesome!
World
Home
Logo
Home
Game
What's the target?
Welcome to DevFest 2018
The first step to address in this application is to identity patterns, what things are reused and what is not
Service
Character
Enemies
World
http://goo.gl/PfqFQX
ngular
We will start by creating a new Module
AngularHero inside the folder app/modules/
ng g m AngularHero
ngular
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
imports: [
CommonModule
]
})
export class AngularHeroModule {
}
app/modules/angular-Hero/angularHero.module.ts
ngular
Lets start the first component
world.component.ts
ng g c world
Component World
import { Component } from '@angular/core';
@Component({
selector: 'world',
providers: [],
styleUrls: [],
templateUrl: './world.component.html'
})
export class WorldComponent {
}
ngular
Component Home
ngular
What we get:
ng g c home
Component App
ngular
ng g c app
Let's add some style
Open index.html and add the following css link in the head section:
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.1/css/materialize.min.css">
Component Goomba
ngular
Now it's your turn, create a Goomba component. Goomba is an enemy of the Super Mario game
ng g c goomba
Add a Goomba to the World module
ngular
<h1>World</h1>
<app-goomba></app-goomba>
world.component.html
Add the component to the module AngularHeroModule.module.ts in the declarations section
Hope things go smoothly...
ngular
Create 3 enemies goompa
Exercise 1
<app-goomba (removeGoomba)="removeGoomba($event)" *ngFor="let enemy of enemies">
</app-goomba>
enemies: Array<string> = ['0', '1', '2'];
Create the character component
Exercise 2
*Note that Mario and Luigi are 2 equally playable characters, so you'll have to make your component flexible to define the character's name
ng g c character
Add Mario and Luigi to the world
Exercise 3
<app-character name="mario" name="Mario" style="background-color:darkred;display:block"></app-character>
<app-character name="luigi" name="Luigi" style="background-color:darkgreen;display:block"></app-character>
Exercise 4
Set Routing
Tell Angular which component to load when navigating
Open app-routing.module.ts
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from "./home/home.component";
const routes: Routes = [
{path: 'home', component: HomeComponent},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Tell to load HomeComponent when navigating in the browser domain.com/home
Mario and Luigi can jumb. Create a button when clicking click on the console that mario or luigi has jumped
Exercise 5
We're going to crush those Goomba. Create a button that allows the goomba to be crushed with a click and as a consequence, the goomba dissapears from the world.
Exercise 6
button
We are going to get some coins.Lets create a service that will supply Mario and Lugi with some coings when they are hit. Make it to show the total coins on each character.
Exercise 7
Let's make the character be the one who crushed the Goomba. As a benefit, each goomba that you crush will recieve 15 more coins
Exercise 8
ngular
All are solved
Otherwise
https://github.com/sajeetharan/DevFestLK2018-ngZeroToHero
Q&A
Rate the session
How to create Angular apps that loaded and executed faster"
https://github.com/sajeetharan/DevFestLK2018-ScalableAngular
$ ng build --prod
$ ng build --prod --build-optimizer=true
$ ng build --prod --source-map
$ >npm i -g source-map-explorer
$> source-map-explorer dist/angular-workshop/main.bundle.js
const appRoutes: Routes = [{
path: 'tweets',
loadChildren: 'tweets/tweets.module#TweetsModule'
}]
const tweetsRoutes: Routes = [{
path: '',
component: TweetFeedsComponent
}];
@NgModule({
imports: [RouterModule.forRoot(appRoutes, {
preloadingStrategy: PreloadAllModules
})],
exports: [RouterModule]
})
<span>{{ relativeDate(tweet.createdAt) }}</span>
<span>{{ tweet.createdAt | relativeDate }}</span>
DOM manipulations are expensive
Immutable practices generate a new DOM collection
Smaller bundles
Template and CSS are inline, which save bunch of server roundtrip
Detect template error earlier build time
Better security
export class TweetListComponent implements OnInit {
...
trackById(index, tweet) {
return tweet.id;
}
}
<div *ngFor="let tweet of tweets; trackBy: trackById">
Angular CLI takes care of tree shaking
Angular 4 has AOT by default Prod mode enabled on production mode CLI
In case of observable you could think of using async pipe using
Don't forget to remove unnecessary if you're not using it.
5 Simple Rules for Components
Should have Single Responsibility
Should be Simple
Should be Small
Should be Encapsulated
Should use Composition
Should have Single Responsibility
Should be Simple
Should be Small
Should be Encapsulated
Should use Composition
LIFT
LOCATE
IDENTIFY
FLAT
TRY DRY
camelCaseForVariablesAndFunctions
dash-case-for-files-and-folders
TitleCaseForClassesAndInterfaces
Quick Recap
...complex systems evolve from simple systems much more rapidly when there are stable intermediate forms...
Herbert A. Simon
Q&A
Rate the session
https://www.rateevent.com/speeches/SCAAA003
Thank you!
Where to go from here?
- Build Applications
- Send your queries @kokkisajee
- Be a part of Ng-SriLanka
- Join Stackoverflowers-SriLanka