Sajeetharan Sinnathurai
With over 13 years of experience in the IT industry, Sajeetharan is a Cloud Solution Architect, an enthusiast in Cloud and Opensource.He currently works at Microsoft as a Senior Program Manager in the CosmosDB team
@kokkisajee
www.sajeetharan.com
In a nutshell
Communities
Social Developer
Recognitions
Cloud Solution Architect @Microsoft
First GDE,MCT and MVP from SL
Top stackoverflow contributor
@sajeetharan
@kokkisajee
@sajeetharan
@sajeetharan
A small story !
@kokkisajee
What the heck is Angular?
@kokkisajee
Why Angular?
Typescript
=
Javascript + Types
Typed JavaScript with #TypeScript
Classes
Types
Interfaces
Private methods
class Person {
private name: string;
private age: number;
private salary: number;
constructor(name: string, age: number, salary: number) {
this.name = name;
this.age = age;
this.salary = salary;
}
toString(): string {
return `${this.name} (${this.age}) (${this.salary})`;
}
}
Angular CLI
Webpack
. 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
Angular App Structure
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...
How this magic happens?
Data Binding
<input [(ngModel)]="name" />
Angular App Hierarchy
Building Blocks of Angular
"MS Dhoni is a Microsoft Certified Professional Developer"
@NgModule
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';
import {AppComponent} from './app.component';
import { HomeComponent } from './home/home.component';
import {AppRoutingModule} from "./app-routing.module";
@NgModule({
declarations: [
AppComponent,
HomeComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
],
providers: [/**DataService, UserService**/],
bootstrap: [AppComponent]
})
export class AppModule {
}
Help organize an application into cohesive blocks of functionality.
This is Angular
The rest is a standard JS/Typescript class
@Component
import {Component, OnInit} from '@angular/core';
import {Router} from "@angular/router";
import {UserService} from "../shared/services/user.service";
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
constructor(private us:UserService, private route: Router) {
}
ngOnInit() {
}
login() {
this.us.login();
}
logout() {
this.us.logout();
}
}
Components are the most basic building block of an UI in an Angular application
Decorator
Annotate this is a Angular component
Angular Injects for us every dependency
@Directives
Components still have directives
<div [ngStyle]="setStyles()">
<p *ngFor="let player of players">...</p>
</div>
Attribute Directives : ngStyle, ngClass, …Structural Directives : ngIf, ngSwitch, ngFor, …
Pipes
Components can display formatted data
import { Pipe } from '@angular/core';
import { PipeTransform } from '@angular/core';
@Pipe({name: 'filterReviewByStatus'})
export class FilterReviewByStatusPipe implements PipeTransform {
}
DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, PercentPipe ...
<p>
The chained mario's birthday is
{{ birthday | date:'fullDate' | uppercase}}
</p>
Services
Components inject services
Service is a class that encapsulates some sort of functionality and provides it as a service for the rest of the application
export class UserService {
private users: User[] = [];
constructor(
private backend: BackendService,
private logger: Logger
) { ... }
getAllUSers() {
return this.users;
}
}
Let's Build
npm install -g @angular/cli
Install:
Generate a our first app:
ng new beerApp --routing --style=scss
cd beerApp
npm start
Create a component
ng g c home
ng generate component home
Using Angular CLI
Short version of the above
What we get:
*Only this file is mandatory for creating a component
Use a component
A component can be used inside another component using its meta data selector
import {Component, OnInit} from '@angular/core';
import {Http, Headers} from "@angular/http";
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(private http: Http) {
}
ngOnInit() {
}
}
home.component.ts
app.component.html
<h1>
App Works!!
</h1>
<app-home></app-home>
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">
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
We keep adding routes for each components we want to navigate
Add a navigation bar
Create a set of links to navigate the app sections. Replace the content of app.component.html with:
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">Logo</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li><a [routerLink]="['/home']">Home</a></li>
<li><a href="">Search Beers</a></li>
<li><a href="">Login</a></li>
</ul>
</div>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
Tell to Angular where to display the content when navigating between components
This is a Directive to link to specific parts of your app.
Home Component
Request to the server
home.component.ts
import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Beer } from '../models/beer';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
beer: Beer;
constructor(private http: HttpClient) {
}
ngOnInit() {
const _options = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
this.http.get('/api/v2/beer/random?key=a81493ef1e81335e3dc2fc1d5e394053&hasLabels=Y', _options).subscribe(
(response: any) => {
const json = response;
this.beer = new Beer();
this.beer.name = json.data.nameDisplay;
this.beer.description = json.data.style.description;
this.beer.image = json.data.labels.medium;
}
);
}
}
Home Component
Display a random beer and set a button to change beer
home.component.html
<div class="col s12 m7">
<h4 class="header">A Random Beer</h4>
<div class="card horizontal">
<div class="card-image">
<img [src]="data.image">
</div>
<div class="card-stacked">
<div class="card-content">
<p>{{ data.description }}</p>
</div>
<div class="card-action">
<a href="#">{{ data.name }}</a>
</div>
</div>
</div>
</div>
String interpolation
Property binding
CORS fix
proxy.json
{
"/api": {
"target": "http://api.brewerydb.com",
"secure": false,
"changeOrigin": true,
"logLevel": "debug",
"pathRewrite": {
"^/api": "/"
}
}
}
Launch the cli with the following
ng serve --proxy-config=proxy.conf.json
Hope things go smoothly..
We should see
Otherwise...
Lfe cycle hooks
•Implemented by components and directives
• Methods which are called when specific events occur
• ngOnChanges() – called when data-bound input properties are set/reset
• ngOnInit() – called shortly after the component is created
• ngOnDestroy() – Called just before Angular destroys the directive component
Search Beer Component
ng g c search-beer
End Point
/api/v2/search?key=a81493ef1e81335e3dc2fc1d5e394053&type=beer
Search for beers using a input field and list them
Search Beer Component
search-beer.component.ts
import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { FormControl } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { switchMap } from 'rxjs/operators';
import { Beer } from '../models/beer';
@Component({
selector: 'app-search-beer',
templateUrl: './search-beer.component.html',
styleUrls: ['./search-beer.component.scss']
})
export class SearchBeerComponent implements OnInit {
termInput = new FormControl();
beers: Beer[] = [];
constructor(private http: HttpClient) {
}
ngOnInit() {
this.termInput.valueChanges.pipe(term => {
return this.search(term);
}).subscribe((res: any) => {
this.beers = res.data;
});
}
search(term) {
return this.http.get(`/api/v2/search?key=a81493ef1e81335e3dc2fc1d5e394053&type=beer&q=${term}`);
}
onKey(value) {
console.log(value);
}
}
Search Beer Component
Next steps:
- Display a list of beers
- Search with the API
- Create a reusable component
Q/A
Want some stickers?
Where to go from here?
- Do the exercise in the given pdf
- Look at Demo Application if you were stuck anytime during the session
- Tweet @kookisajee
- We will meet again with the session "High level Angular application architecture"
- Join Stackoverflowers-SriLanka and volunteer Ng-SriLanka
By Sajeetharan Sinnathurai
With over 13 years of experience in the IT industry, Sajeetharan is a Cloud Solution Architect, an enthusiast in Cloud and Opensource.He currently works at Microsoft as a Senior Program Manager in the CosmosDB team