SlideShare a Scribd company logo
Installation
NodeJS
VS Code
Angular CLI (https://angular.io/cli)
npm install -g @angular/cli (@abc/xyz is called "scoped" package name. These
names are of the format @group/package)
ng version
ng new first-project
Is
cd first-project
Is
Open project in VS Code
To run the project
ng serve
On browser http://localhost:4200/
Check index.html file
app-root component is available in app folder
app.component.ts, app.component.html and app.component.css files provide
functionality and look and feel of app component
A component is a combination of view and backing logic
app.component.ts provides backing logic, app.component.html and
app.component.css files providelook and feel of app component
Make a change in index.html and check in browser
Make a change in app.component.ts
title = 'My first-project'’;
Dynamic logic will come from type script file
Make a change in app.component.css
h1{
color: red;
}
app.component.spec.ts is for test case
Delete all the content in app.component.html and save
Creating your first component
In terminal stop the server (Ctrl C)
Create a new component
ng generate component hello-world
Check in VS Code
Check hello-world.component.ts
You have a selector for it which is going to instantiate this component. You can use
the selector in html markup of a component and then it is going to call it as a child
component
Open app.component.html file
Run the server ng serve
We have created a component and use it in another component
You can use hello-world component multiple times and it is going to create those
many instances
Check in browser
Anatomy of a component
We want to make a date component which prints current date
Open terminal in VS Code
ng generate component date
Open date-component.ts and see the selector
In app.component.html
<app-date></app-date>
Check it
Every angular component is mainly a typescript class. Think of the HTML and
CSS as just extra "attachments" to the main typescript file.
So angular CLI creates a class for a component. Or in order to create a component
you have to create a typescript class (if you were to do it yourself). After you have
created the class you need to register the class as an angular componert. It is done
with @Component annotation. You can try changing selector template
Url attributes
and also do required changes and can try it out(In date.component.ts file )
Binding data from component class
Create a member variable in DateComponent class
message: string = "hello";
In date.component.html file
{{message}}
Check it in browser
Now instead of "hello" text change it to new Date()
message: string = new Date().toDateString(); (or toString)
In date.component.html file
<div>
<p>The date is:</p>
<p>
{{message}}
</p>
</div>
Data binding in Angular refers to binding the data in the component instance
to the HTML template. Any change to the data get automatically updated in the
view.
Right now it is one way flow of data - from component to html
Data binding and async
We want to constantly update time
export class DateComponent implements Onlnit {
dateMessage: string;
constructor() {
let currentDate=new Date()
this.dateMessage=currentDate.toDateString()+'
'+currentDate.toLocaleTimeString()
}
ngOnInit(): void {
}
}
And in html file
<div>
<p>The date is:</p>
<p>
{{dateMessage}}
</p>
</div>
Right now the new Date object is created in constructor. So, it currently only
executes when the page is loaded which causes the component instance to be
created.
In oorder to update time we need to create new Date object every second. So we'll
use setlnterval in constructor
export class DateComponent implements Onlnit {
dateMessage: string | undefined;
constructor() {
setinterval(() => {
let currentDate = new Date()
this.dateMessage = currentDate.toDateString() + '' +
currentDate.toLocaleTimeString()
}, 1000)
}
ngOnInit(): void {
}
}
Check in browser
Template Interpolation
Text interpolation lets you incorporate dynamic string values into your HTML
templates.Interpolation refers to embedding expressions into marked up text. By
default, interpolation uses the double curly braces {{ and }} as delimiters.
{{dateMessage}}-double curly brackets trigger angular to do string interpolation
In html
{{1+1}}
Define a num variable in class
{{num*2}}
Now double curly brackets with function call
import { Component, Onlnit } from ‘@angular/core’;
@Component({
selector: 'app-date’,
templateUrl: './date.component.htm’,
styleUrls: ['./date.component.css']
})
export class DateComponent implements Onlnit {
dateMessage: string | undefined;
num: number=1
2;
constructor() {
setinterval(() => {
let currentDate = new Date()
this.dateMessage = currentDate.toDateString() + '' +
currentDate.toLocaleTimeString()
}, 1000)
}
ngOnlnit(): void {
add(a:number,b:number}{
return a+b
}
}
And in html file
<div>
<p>The date is:</p>
<p>
{{dateMessage}}
</p>
{{num*2}}<br>
{{add(num,2)}}
</div>
Check it
this is required in class but not in html
import { Component, Onlnit } from '@angular/core’;
@Component({
selector: 'app-date’,
templateUrl: './date.component.htm’,
styleUrls: ['./date.component.css']
})
export class DateComponent implements Onlnit {
dateMessage: string | undefined;
num: number=1
2;
constructor() {
setinterval(() => {
let currentDate = new Date()
this.dateMessage = currentDate.toDateString() + '' +
currentDate.toLocaleTimeString()
}, 1000)
}
ngOnlnit(): void {
add(a:number,b:number}{
return a+b
}
someMeth() //here
this.add(this.num,2)
}
}
Looping with ngFor
Make a new seconc-project
Clear code from app.component.htm|
and delete line title = 'app'; in app.component.ts
Check with ng serve
Stop the server and create new component address card
ng generate component address-card
It get registered in app.module.ts
To check address-card component works, from address-card.component.ts file take
the selector and use it in app.component.html file
<app-address-card></app-address-card>
Now in address-card.component.html
<div>
<h1>NU</hi>
<h3>Computer</h3>
<p>NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705</p>
<div>
<p>Phone:</p>
<p>123-456-7890</p>
<p>345-789-1234</p>
</div>
</div>
Now we con't want it to be hard coded we want it dynamic
So in address-card.component.ts we'll create a user object
import { Component, Onlnit } from ‘@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user={
name:'NU',
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
phone:
123-456-7890",
345-789-1234"
|
}
constructor() { }
ngOnInit(): void {
}
}
Now this user object needs to be in constructor
import { Component, Onlnit } from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
constructor() {
this.user={
name:NU’,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
phone:|
123-456-7890",
"345-789-1234"
|
}
}
ngOnInit(): void {
}
}
Now in address-card.component.html file
<div>
<h1>{{user.name}}</h1>
<h3>{{user.title}}</h3>
<p>{{user.address}}</p>
<div>
<p>Phone:</p>
<p>{{user.phone[0]}}</p>
<p>{{user.phone[1]}}</p>
</div>
</div>
Now we want to loop through phone values
<div>
<h1>{{user.name}}</h1>
<h3>{{user.title}}</h3>
<p>{{user.address}}</p>
<div>
<p>Phone:</p>
<p *ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
Now add another phone number in address-card.component.ts file and check
ngFor is a directive. A directive is something that you add to an element.
nglf
What if there is no phone number
import { Component, Onlnit } from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
constructor() {
this.user={
name:NU’,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
}
}
ngOnInit(): void {
}
}
But Phone: still appears
Now we con't want to display when there are no phone numbers
<div>
<h1>{{user.name}}</h1>
<h3>{{user.title}}</h3>
<p>{{user.address}}</p>
<div *nglf="user.phone.length>0">
<p>Phone:</p>
<p *ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
nglf is not hiding the div element, it is removing it from the dom, if the expression
evaluates to false
This will also work
<div *nglf="user.phone.length">
Also check by adding phone numbers
import { Component, Onlnit} from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
constructor() {
this.user={
name:NU’,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
phone:|
123-456-7890",
"345-789-1234"
|
}
}
ngOnInit(): void {
}
}
Passing input to component
We want to pass the data
<app-address-card name="NIIT University"></app-address-card>
and in address-card.component.ts (Move the code from constructor to ngOnInit())
import { Component, Input, Onlnit } from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
@Input(‘name') userName: string | undefined;
constructor() {
}
ngOnlnit(): void {
this.user={
name:this.userName,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
ngOninit - executes code when component is fully initialized. A lifecycle hook
that is called after Angular has initialized all data-bound properties of a
directive.
https://v2.angular.io/docs/ts/latest/guide/lifecycle-hooks.html
https ://angular.io/guide/lifecycle-hooks
When you use a selector angular creates an instance of a class. So the constructor
is executed
constructor - you can write code when object is created. (e.g. to populate data)
Angular also does few other things after object is created (e.g. @Input). So
after creating object it populates the values. It is after the creation of object
that angular populates the value. You want to run the code once object has
been fully created and initialized. You cannot run that code in the constructor.
Angular provides Life cycle hooks for it. When angular object is fully initialized
it will call ngOnInit method(). So you can write your @Input code in ngOnInit
method.
You can write the code without “implements Onlnit". It is only for compile checking
for developer. The code would run the same. Angular is not looking for the interface,
it is looking for the method (e.g. ngOnInit())
Passing member variables to components
Apart from name passing we can pass other attributes of Address. That would be
tedious. Instead we can pass an object which will contain all the values that the
address-card component need. In order to create that object we need to create a
class as an API for our component.
In address-card folder create a new file user.model.ts
export class User{
name: string
designation: string
address: string
phone: string []
}
The definite assignment assertion is a feature that allows a! to be placed after
instance property and variable declarations to relay to TypeScript that a
variable is indeed assigned for all intents and purposes, even if TypeScript’s
analyses cannot detect so.
Now in address-card.component.ts
import { Component, Input, Onlnit} from '@angular/core’;
import { User } from './user.model';
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
@Input(‘user')
userOb}!: User;
constructor() {
}
ngOnlnit(): void {
this.user={
name:this.userObj.name,
title:this. userObj.designation,
address:this.userObj.address,
phone:this.userObj.phone
}
In order to pass an instance of user - you need to first create that instance in
app.component.ts file. App component is using address card component. App
component need to pass instance of user to address-card component. In order to do
that it need to create that instance first.
Now in app.component.ts file (we'll make an instance of User)
import { Component } from '@angular/core’;
import { User } from './address-card/user.model';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm’,
styleUrls: ['./app.component.css']
})
export class AppComponent {
user!: User;
constructor(){
this.user=new User()
this.user.name="NU"
this.user.designation="Computer"
this. user.address="Neemrana"
this.user.phone=[
'123-456-7890'
]
}
Now in app.component.html
<app-address-card user="user"></app-address-card>
will give error (because user is being assigned a string value - user)
To evaluate the user
<app-address-card [user]="user"></app-address-card>
This telles angular not to take the value inline , instead evaluate it and take the
member variable that it refers to.
Styling angular components
address-card.component.css
.address-card{
border: 1px gray solid;
padding: 15px;
}
-name{
font-family: "verdana", sans-serif;
}
.title{
font-style: italic;
}
.address{
font-size: 15x;
}
.phone{
border-left: 1px gray solid;
padding-left: 5px;
}
Now | want class name, title etc only if the class happen in address-card class
element (<div class="address-card">). So if there is another class title in html and
you don't want it to be style like italic. You want only want "title" which is inside
address-card to be style with italic.
And in address-card.component.html
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</n3>
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p *ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
Now in app.component.html add a line
<p class="title">Sample text</p>
But it doesn't turn italic. Because the style that we apply in our
address-card.component.css applies only to the markup inside the component.
Now move this line <p class="title">Sample text</p> in
address-card-component.html. Now it would work.
This works because the way angular manages styling. Check in browser console.(An
additional style has been appended to it). The [property] selector is used in CSS to
style elements that have that particular property. This is angular trying to insulate
styling that you are applying only to that component. It is intentional.
Now how to apply global style?. You have global styles.css file (in src folder)
Handling click event
Expand and Collapse button for address
Open address-card.component.ts file
isCollapsed:boolean =true;
Now in address-card.component.html file (address and phone should be in a div -
because we want expand/collapse for both of them together)
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</n3>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Now add a button in html (Expand/Collapse)
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</n3>
<button>Expand / Collapse</button>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Define a function in address-card.component.ts file
toggleCollapse(){
this.isCollapsed=!this.isCollapsed;
}
Now to call that function we will not use browser click event handler like
<button onclick="abc()">. We want to call API of angular.
So in address-card.component.html file
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</h3>
<button (click)="toggleCollapse()">Expand / Collapse</button>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Now to show right text - Expand or Collapse
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</h3>
<button *nglf="isCollapsed" (click)="toggleCollapse()">Expand</button>
<button *nglf="!isCollapsed" (click)="toggleCollapse()">Collapse</button>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Two way data binding with ngModel (it can be used with forms)
You update the component and view gets updated and vice versa.
Open app.component.html file
<input type="text'/>
In app.component.ts file add instance variable
inputText: string="Manish"
And in app.component.html file
<input type="text" value="inputText"/>
In order to angular evaluate it put it in []
<input type="text" [value]="inputText"/>
Now to map it
In app.component.html file
<app-address-card [user]="user"></app-address-card>
<input type="text" [value]="inputT ext"/><br>
{{inputText}}
Check it. Right now it is not showing the change. Because right now there is only
one way data binding.
To use two way data binding use ngModel directive
In app.component.html file
<app-address-card [user]="user"></app-address-card>
<input type="text" ngModel="inputText"/><br>
{{inputText}}
In order to use ngModel we need to make one more change - module.
To use ngModel you need to import standard angular module in app.module.ts
In app.module.ts (in NgModule section->imports)
imports: [
BrowserMocule,
AppRoutingModule,
FormsModule
1,
and the right import for FormsModule
import { FormsModule } from '@angular/forms';
In app.component.html file (use [] with ngModel)
<app-address-card [user]="user"></app-address-card>
<input type="text" [ngModel]="inputText"/><br>
{{inputText}}
But it still doesn't works (because right now it is one way binding)
To make it two way use [()]
<app-address-card [user]="user"></app-address-card>
<input type="text" [(ngModel)]="inputText"/><br><br>
{{inputText}}
The [()] syntax is referred to as banana-in-a-box.
It helps to remember the order: brackets outside, parenthesis inside.
0 -> data flowing from the component to the view
()-> data from view to component
(Compare click event made above)
Creating and using multiple
Create a new project third-project
ng new third-project
and delete the content of app.component.html file
Open app.module.ts
A module is a thing that consolidates different components. It does a lot more
than that. Think of a module as some kind of container, some kind of
namspace tha contains different things (e.g. AppComponent). So
AppComponent is a part of AppModule. You can create multiple modules ina
project and each module is going to contain components within it. So
AppModule is a container for AppComponent. So modules might be required
for big applications.
To create a module
ng generate module view
It has created a folder view in app folder and a class in it
And it does not have any declarations (there are no components associated with it
now)
It just have one import - CommonModule
Now to create a component inside this module
ng generate component view-component //don't run it
But by default angular cli will create this component in app.module.ts (because that's
where the root is (we are executing this command from the root - will assume that
this component in app module))
But we want to create this component in view module
So prefix with module name
ng generate component view/view-component
Notice it update view.module.ts file
In declarations of view.module.ts file ViewComponentComponent has been added.
We can also co all these things manually (without angular cli- by createing
respective files and folders)
Now ViewComponent is part of View Module (and it is nota part of app module)
Open view-component.component.ts file and look at the selector.
Now use this selector (in app module) app.component.html.
It fails to compile. In browser inspector it will show app-view-component not known.
To make it work in app.module.ts import ViewModule
But it still doesn't works
Because view.module.ts is working with a component that it is not exporting it.
So in view.module.ts
import { NgModule } from '@angular/core’;
import { CommonModule } from '@angular/common';
import { ViewComponentComponent } from
" view-component/view-component.component’;
@NgModcule({
declarations: [
ViewComponentComponent
1
imports: [
CommonModule
],
exports: [
ViewComponentComponent
]
})
export class ViewModule { }
So all in all
1. The module that need it, needs to import the module, whatever module the
component is declared in
2. Whatever module the component is declared in has to export the component
Create a service
If you want to create business functionality which doesn't have a view - you can
create services. Services are like classes as components are.
ng generate service test
It will create a service in app location
Open test.service.ts file
@Injectable annotation tells angular that this class is a service.
(@Component - Angular Component)
(@NgModule - Angular module)
(@Injectable - Angular service)
Its reference is not added in app.module.ts file
Now if you want test.service.ts to be part of app module then you need to declare in
@NgModule. Services that you use in your modules need to be listed in providers
section of your @NgModule
providers:|
TestService
|
In test.service.ts file
import { Injectable } from '@angular/core’;
@Injectable({
providedIn: 'root'
})
export class TestService {
printToConsole(arg: any){
console.log(arg)
}
constructor() { }
}
Now to call this method printToConsole we'll use Dependency Injection
Dependency Injection
We want to call printfoConsole method from AppComponent class
First - let us call the method by using instance
constructor(){
let svc=new TestService()
svc.printtoConsole("Manish")
}
But in this scenario we are binding TestService with AppComponent class
Second way - Dependeny Injection
The idea of dependency injection is that when yo have a class that is dependent on
another class - you don't have that class create that instance. What you do instead
have the class declare its dependency and have that dependency injected.
All you need to do declare a dependency on other services is just to create
constructor arguments. Angular is going to look at the constructor and its arguments
and it is going to see if any of these arguments are @Injectable. If there are services
- angular is going to find that service (otherwise it will create one) and then it is going
to pass that into the constructor (when this component is being created)
In app.component.ts file
import { Component } from '@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.html’,
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(svc: TestService){
svc.printtoConsole("Manish")
}
title = 'third-project’;
}
Check it in browser console.
Now it is available till the constructor runs. We can store it in instance variable. A
shortcut for doing it.
import { Component } from '‘@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private svc:TestService
constructor(svc: TestService){
this.svc=svc;
svc.printTtoConsole("Manish")
}
title = 'third-project’;
}
Or a shortcut
import { Component } from '@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
‘private svc:TestService
constructor(private svc: TestService){
//this.svc=svc;
this.svc.printToConsole("Manish")
}
title = 'third-project’;
}
Service Injection Context
Difference between the components operate and the services operate in the context
of module. A component can be declared inside module, in which case the
component is only available to other components in the module. If you want to make
it available outside the module you need to mark it in export; you need to add
component in the exports and then other module needs it has to import. Ifa
component has to be used outside its module - 2 rules
1. Owning module needs to export it
2. Then the module thats trying to use it needs to import the module.
But in case of services it works differently.
In app.module.ts - TestService has been provided in App module. You have added it
in the providers section in the module. Now you can cdo dependency injection inside
app.component.ts. Now there is another component - view component in the same
project. Now what happens if we use dependency injection in
view-component.component.ts and get access to TestService
import { Component, Onlnit} from '@angular/core’;
import { TestService } from ‘src/app/test.service';
@Component({
selector: 'app-view-component,
templateUrl: './view-component.component.html’,
styleUrls: ['.view-component.component.css']
})
export class ViewComponentComponent implements Onlnit {
constructor(private svc: TestService) {
svc.printtoConsole("From view module")
}
ngOnInit(): void {
}
}
Now view.module.ts is not dependent on App module. It is other way round. The App
module imports the view module. So can the view component access the service
that is inside App component? 
We have seen it works.
How is it possible? It is possible because of the way services works in Angular.
Services are not restricted to the module that they are provided in. App module has
TestService in providers. In the case of a component (e.g.AppComponent) that
component is only available in the module. But i case of service (or providers)
Angular creates a common shared space for services. There is a common area that
contains all the services in your application that anybody cann add too. Let's suppos
you have 3 different modules (each having different providers). Those providers are
not restricted to that module. They become part of this common shared service
space and any other component that makes a dependency injection which declares
its dependency on any of the services is going to get the instance of that service. It
doesn't have to be part of the module. The shared service space is referred as
Injection context (Dependency Injection context). This list is available to all the
components in your application. This is the reason why when Angular CLI created
service it did not automatically added to any of the module. It did not Know where to
provide TestService.
REST with HttpClient
How co you make REST API call with Angular? There is a service called HttpClient.
In order to use that service import the module that the service comes with. The
module contains service and the providers section. So when you import that module
that service get added in injection context so that it is available to all your
components.
In app.module.ts
import { NgModule } from '@angular/core’;
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http’;
import { AppRoutingModule } from './app-routing. module’;
import { AppComponent } from './app.component;
import { TestService } from '/test.service';
import { ViewModule } from '/view/view.module’;
@NgModcule({
declarations: [
AppComponent
1
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
ViewModule
1,
providers: [TestService],
bootstrap: [AppComponent]
})
export class AppModule { }
Now in app.component.ts (we'll inject service HttpClient)
ngOnInit(}{
//let response =this. http.get(‘https://api.github.com/users/koushikkothagal’)
//Can't do since you get an async object and in Angular world it is called
Observable (earlier in Angular JS it was called promise)
}
In app.component.ts
import { HttpClient } from '‘@angular/common/http’;
import { Component } from '@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
‘private svc:TestService
constructor(private svc: TestService, private http:HttpClient){
//this.svc=svc;
this.svc.printToConsole("Manish")
}
ngOniInit(){
//let response =this. http.get(‘https://api.github.com/users/koushikkothagal’)
//Can't do since it is an async request
let obs=this.http.get(‘https://api.github.com/users/koushikkothagal’)
obs.subscribe(()=>console.log("Got the response"))
}
title = 'third-project’;
}
Check in browser
Change it to
obs.subscribe((response)=>console.log(response))
Installation
NodeJS
VS Code
Angular CLI (https://angular.io/cli)
npm install -g @angular/cli (@abc/xyz is called "scoped" package name. These
names are of the format @group/package)
ng version
ng new first-project
Is
cd first-project
Is
Open project in VS Code
To run the project
ng serve
On browser http://localhost:4200/
Check index.html file
app-root component is available in app folder
app.component.ts, app.component.html and app.component.css files provide
functionality and look and feel of app component
A component is a combination of view and backing logic
app.component.ts provides backing logic, app.component.html and
app.component.css files providelook and feel of app component
Make a change in index.html and check in browser
Make a change in app.component.ts
title = 'My first-project'’;
Dynamic logic will come from type script file
Make a change in app.component.css
h1{
color: red;
}
app.component.spec.ts is for test case
Delete all the content in app.component.html and save
Creating your first component
In terminal stop the server (Ctrl C)
Create a new component
ng generate component hello-world
Check in VS Code
Check hello-world.component.ts
You have a selector for it which is going to instantiate this component. You can use
the selector in html markup of a component and then it is going to call it as a child
component
Open app.component.html file
Run the server ng serve
We have created a component and use it in another component
You can use hello-world component multiple times and it is going to create those
many instances
Check in browser
Anatomy of a component
We want to make a date component which prints current date
Open terminal in VS Code
ng generate component date
Open date-component.ts and see the selector
In app.component.html
<app-date></app-date>
Check it
Every angular component is mainly a typescript class. Think of the HTML and
CSS as just extra "attachments" to the main typescript file.
So angular CLI creates a class for a component. Or in order to create a component
you have to create a typescript class (if you were to do it yourself). After you have
created the class you need to register the class as an angular componert. It is done
with @Component annotation. You can try changing selector template
Url attributes
and also do required changes and can try it out(In date.component.ts file )
Binding data from component class
Create a member variable in DateComponent class
message: string = "hello";
In date.component.html file
{{message}}
Check it in browser
Now instead of "hello" text change it to new Date()
message: string = new Date().toDateString(); (or toString)
In date.component.html file
<div>
<p>The date is:</p>
<p>
{{message}}
</p>
</div>
Data binding in Angular refers to binding the data in the component instance
to the HTML template. Any change to the data get automatically updated in the
view.
Right now it is one way flow of data - from component to html
Data binding and async
We want to constantly update time
export class DateComponent implements Onlnit {
dateMessage: string;
constructor() {
let currentDate=new Date()
this.dateMessage=currentDate.toDateString()+'
'+currentDate.toLocaleTimeString()
}
ngOnInit(): void {
}
}
And in html file
<div>
<p>The date is:</p>
<p>
{{dateMessage}}
</p>
</div>
Right now the new Date object is created in constructor. So, it currently only
executes when the page is loaded which causes the component instance to be
created.
In oorder to update time we need to create new Date object every second. So we'll
use setlnterval in constructor
export class DateComponent implements Onlnit {
dateMessage: string | undefined;
constructor() {
setinterval(() => {
let currentDate = new Date()
this.dateMessage = currentDate.toDateString() + '' +
currentDate.toLocaleTimeString()
}, 1000)
}
ngOnInit(): void {
}
}
Check in browser
Template Interpolation
Text interpolation lets you incorporate dynamic string values into your HTML
templates.Interpolation refers to embedding expressions into marked up text. By
default, interpolation uses the double curly braces {{ and }} as delimiters.
{{dateMessage}}-double curly brackets trigger angular to do string interpolation
In html
{{1+1}}
Define a num variable in class
{{num*2}}
Now double curly brackets with function call
import { Component, Onlnit } from ‘@angular/core’;
@Component({
selector: 'app-date’,
templateUrl: './date.component.htm’,
styleUrls: ['./date.component.css']
})
export class DateComponent implements Onlnit {
dateMessage: string | undefined;
num: number=1
2;
constructor() {
setinterval(() => {
let currentDate = new Date()
this.dateMessage = currentDate.toDateString() + '' +
currentDate.toLocaleTimeString()
}, 1000)
}
ngOnlnit(): void {
add(a:number,b:number}{
return a+b
}
}
And in html file
<div>
<p>The date is:</p>
<p>
{{dateMessage}}
</p>
{{num*2}}<br>
{{add(num,2)}}
</div>
Check it
this is required in class but not in html
import { Component, Onlnit } from '@angular/core’;
@Component({
selector: 'app-date’,
templateUrl: './date.component.htm’,
styleUrls: ['./date.component.css']
})
export class DateComponent implements Onlnit {
dateMessage: string | undefined;
num: number=1
2;
constructor() {
setinterval(() => {
let currentDate = new Date()
this.dateMessage = currentDate.toDateString() + '' +
currentDate.toLocaleTimeString()
}, 1000)
}
ngOnlnit(): void {
add(a:number,b:number}{
return a+b
}
someMeth() //here
this.add(this.num,2)
}
}
Looping with ngFor
Make a new seconc-project
Clear code from app.component.htm|
and delete line title = 'app'; in app.component.ts
Check with ng serve
Stop the server and create new component address card
ng generate component address-card
It get registered in app.module.ts
To check address-card component works, from address-card.component.ts file take
the selector and use it in app.component.html file
<app-address-card></app-address-card>
Now in address-card.component.html
<div>
<h1>NU</hi>
<h3>Computer</h3>
<p>NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705</p>
<div>
<p>Phone:</p>
<p>123-456-7890</p>
<p>345-789-1234</p>
</div>
</div>
Now we con't want it to be hard coded we want it dynamic
So in address-card.component.ts we'll create a user object
import { Component, Onlnit } from ‘@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user={
name:'NU',
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
phone:
123-456-7890",
345-789-1234"
|
}
constructor() { }
ngOnInit(): void {
}
}
Now this user object needs to be in constructor
import { Component, Onlnit } from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
constructor() {
this.user={
name:NU’,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
phone:|
123-456-7890",
"345-789-1234"
|
}
}
ngOnInit(): void {
}
}
Now in address-card.component.html file
<div>
<h1>{{user.name}}</h1>
<h3>{{user.title}}</h3>
<p>{{user.address}}</p>
<div>
<p>Phone:</p>
<p>{{user.phone[0]}}</p>
<p>{{user.phone[1]}}</p>
</div>
</div>
Now we want to loop through phone values
<div>
<h1>{{user.name}}</h1>
<h3>{{user.title}}</h3>
<p>{{user.address}}</p>
<div>
<p>Phone:</p>
<p *ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
Now add another phone number in address-card.component.ts file and check
ngFor is a directive. A directive is something that you add to an element.
nglf
What if there is no phone number
import { Component, Onlnit } from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
constructor() {
this.user={
name:NU’,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
}
}
ngOnInit(): void {
}
}
But Phone: still appears
Now we con't want to display when there are no phone numbers
<div>
<h1>{{user.name}}</h1>
<h3>{{user.title}}</h3>
<p>{{user.address}}</p>
<div *nglf="user.phone.length>0">
<p>Phone:</p>
<p *ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
nglf is not hiding the div element, it is removing it from the dom, if the expression
evaluates to false
This will also work
<div *nglf="user.phone.length">
Also check by adding phone numbers
import { Component, Onlnit} from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
constructor() {
this.user={
name:NU’,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
phone:|
123-456-7890",
"345-789-1234"
|
}
}
ngOnInit(): void {
}
}
Passing input to component
We want to pass the data
<app-address-card name="NIIT University"></app-address-card>
and in address-card.component.ts (Move the code from constructor to ngOnInit())
import { Component, Input, Onlnit } from '@angular/core’;
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
@Input(‘name') userName: string | undefined;
constructor() {
}
ngOnlnit(): void {
this.user={
name:this.userName,
title:‘Computer’,
address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’,
ngOninit - executes code when component is fully initialized. A lifecycle hook
that is called after Angular has initialized all data-bound properties of a
directive.
https://v2.angular.io/docs/ts/latest/guide/lifecycle-hooks.html
https ://angular.io/guide/lifecycle-hooks
When you use a selector angular creates an instance of a class. So the constructor
is executed
constructor - you can write code when object is created. (e.g. to populate data)
Angular also does few other things after object is created (e.g. @Input). So
after creating object it populates the values. It is after the creation of object
that angular populates the value. You want to run the code once object has
been fully created and initialized. You cannot run that code in the constructor.
Angular provides Life cycle hooks for it. When angular object is fully initialized
it will call ngOnInit method(). So you can write your @Input code in ngOnInit
method.
You can write the code without “implements Onlnit". It is only for compile checking
for developer. The code would run the same. Angular is not looking for the interface,
it is looking for the method (e.g. ngOnInit())
Passing member variables to components
Apart from name passing we can pass other attributes of Address. That would be
tedious. Instead we can pass an object which will contain all the values that the
address-card component need. In order to create that object we need to create a
class as an API for our component.
In address-card folder create a new file user.model.ts
export class User{
name: string
designation: string
address: string
phone: string []
}
The definite assignment assertion is a feature that allows a! to be placed after
instance property and variable declarations to relay to TypeScript that a
variable is indeed assigned for all intents and purposes, even if TypeScript’s
analyses cannot detect so.
Now in address-card.component.ts
import { Component, Input, Onlnit} from '@angular/core’;
import { User } from './user.model';
@Component({
selector: 'app-address-card’,
templateUrl: './address-card.component.htm'’,
styleUrls: ['./address-card.component.css']
})
export class AddressCardComponent implements Onlnit {
user: any;
@Input(‘user')
userOb}!: User;
constructor() {
}
ngOnlnit(): void {
this.user={
name:this.userObj.name,
title:this. userObj.designation,
address:this.userObj.address,
phone:this.userObj.phone
}
In order to pass an instance of user - you need to first create that instance in
app.component.ts file. App component is using address card component. App
component need to pass instance of user to address-card component. In order to do
that it need to create that instance first.
Now in app.component.ts file (we'll make an instance of User)
import { Component } from '@angular/core’;
import { User } from './address-card/user.model';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm’,
styleUrls: ['./app.component.css']
})
export class AppComponent {
user!: User;
constructor(){
this.user=new User()
this.user.name="NU"
this.user.designation="Computer"
this. user.address="Neemrana"
this.user.phone=[
'123-456-7890'
]
}
Now in app.component.html
<app-address-card user="user"></app-address-card>
will give error (because user is being assigned a string value - user)
To evaluate the user
<app-address-card [user]="user"></app-address-card>
This tells angular not to take the value inline , instead evaluate it and take the
member variable that it refers to.
Styling angular components
address-card.component.css
.address-card{
border: 1px gray solid;
padding: 15px;
}
-name{
font-family: "verdana", sans-serif;
}
.title{
font-style: italic;
}
.address{
font-size: 15x;
}
.phone{
border-left: 1px gray solid;
padding-left: 5px;
}
Now | want class name, title etc only if the class happen in address-card class
element (<div class="address-card">). So if there is another class title in html and
you don't want it to be style like italic. You want only want "title" which is inside
address-card to be style with italic.
And in address-card.component.html
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</n3>
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p *ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
Now in app.component.html add a line
<p class="title">Sample text</p>
But it doesn't turn italic. Because the style that we apply in our
address-card.component.css applies only to the markup inside the component.
Now move this line <p class="title">Sample text</p> in
address-card-component.html. Now it would work.
This works because the way angular manages styling. Check in browser console.(An
additional style has been appended to it). The [property] selector is used in CSS to
style elements that have that particular property. This is angular trying to insulate
styling that you are applying only to that component. It is intentional.
Now how to apply global style?. You have global styles.css file (in src folder)
Handling click event
Expand and Collapse button for address
Open address-card.component.ts file
isCollapsed:boolean =true;
Now in address-card.component.html file (address and phone should be in a div -
because we want expand/collapse for both of them together)
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</n3>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Now add a button in html (Expand/Collapse)
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</n3>
<button>Expand / Collapse</button>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Define a function in address-card.component.ts file
toggleCollapse(){
this.isCollapsed=!this.isCollapsed;
}
Now to call that function we will not use browser click event handler like
<button onclick="abc()">. We want to call API of angular.
So in address-card.component.html file
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</h3>
<button (click)="toggleCollapse()">Expand / Collapse</button>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Now to show right text - Expand or Collapse
<div class="address-card">
<h1 class="name">{f{fuser.name}}</h1>
<h3 class="title">{{user.title}}</h3>
<button *nglf="isCollapsed" (click)="toggleCollapse()">Expand</button>
<button *nglf="!isCollapsed" (click)="toggleCollapse()">Collapse</button>
<div *nglf="tisCollapsed">
<p class="address">{{user.address}}</p>
<div class="phone" *nglf="user.phone.length">
<p>Phone:</p>
<p “ngFor="let phNum of user.phone">{{phNum}}</p>
</div>
</div>
</div>
<p class="title">Sample text</p>
Two way data binding with ngModel (it can be used with forms)
You update the component and view gets updated and vice versa.
Open app.component.html file
<input type="text'/>
In app.component.ts file add instance variable
inputText: string="Manish"
And in app.component.html file
<input type="text" value="inputText"/>
In order to angular evaluate it put it in []
<input type="text" [value]="inputText"/>
Now to map it
In app.component.html file
<app-address-card [user]="user"></app-address-card>
<input type="text" [value]="inputT ext"/><br>
{{inputText}}
Check it. Right now it is not showing the change. Because right now there is only
one way data binding.
To use two way data binding use ngModel directive
In app.component.html file
<app-address-card [user]="user"></app-address-card>
<input type="text" ngModel="inputText"/><br>
{{inputText}}
In order to use ngModel we need to make one more change - module.
To use ngModel you need to import standard angular module in app.module.ts
In app.module.ts (in NgModule section->imports)
imports: [
BrowserMocule,
AppRoutingModule,
FormsModule
1,
and the right import for FormsModule
import { FormsModule } from '@angular/forms';
In app.component.html file (use [] with ngModel)
<app-address-card [user]="user"></app-address-card>
<input type="text" [ngModel]="inputText"/><br>
{{inputText}}
But it still doesn't works (because right now it is one way binding)
To make it two way use [()]
<app-address-card [user]="user"></app-address-card>
<input type="text" [(ngModel)]="inputText"/><br><br>
{{inputText}}
The [()] syntax is referred to as banana-in-a-box.
It helps to remember the order: brackets outside, parenthesis inside.
0 -> data flowing from the component to the view
()-> data from view to component
(Compare click event made above)
Creating and using multiple modules
Create a new project third-project
ng new third-project
and delete the content of app.component.html file
Open app.module.ts
A module is a thing that consolidates different components. It does a lot more
than that. Think of a module as some kind of container, some kind of
namspace tha contains different things (e.g. AppComponent). So
AppComponent is a part of AppModule. You can create multiple modules ina
project and each module is going to contain components within it. So
AppModule is a container for AppComponent. So modules might be required
for big applications.
To create a module
ng generate module view
It has created a folder view in app folder and a class in it
And it does not have any declarations (there are no components associated with it
now)
It just have one import - CommonModule
Now to create a component inside this module
ng generate component view-component //don't run it
But by default angular cli will create this component in app.module.ts (because that's
where the root is (we are executing this command from the root - will assume that
this component in app module))
But we want to create this component in view module
So prefix with module name
ng generate component view/view-component
Notice it update view.module.ts file
In declarations of view.module.ts file ViewComponentComponent has been added.
We can also co all these things manually (without angular cli- by createing
respective files and folders)
Now ViewComponent is part of View Module (and it is nota part of app module)
Open view-component.component.ts file and look at the selector.
Now use this selector (in app module) app.component.html.
It fails to compile. In browser inspector it will show app-view-component not known.
To make it work in app.module.ts import ViewModule
But it still doesn't works
Because view.module.ts is working with a component that it is not exporting it.
So in view.module.ts
import { NgModule } from '@angular/core’;
import { CommonModule } from '@angular/common';
import { ViewComponentComponent } from
" view-component/view-component.component’;
@NgModcule({
declarations: [
ViewComponentComponent
1
imports: [
CommonModule
],
exports: [
ViewComponentComponent
]
})
export class ViewModule { }
So all in all
1. The module that need it, needs to import the module, whatever module the
component is declared in
2. Whatever module the component is declared in has to export the component
Create a service
If you want to create business functionality which doesn't have a view - you can
create services. Services are like classes as components are.
ng generate service test
It will create a service in app location
Open test.service.ts file
@Injectable annotation tells angular that this class is a service.
(@Component - Angular Component)
(@NgModule - Angular module)
(@Injectable - Angular service)
Its reference is not added in app.module.ts file
Now if you want test.service.ts to be part of app module then you need to declare in
@NgModule. Services that you use in your modules need to be listed in providers
section of your @NgModule
providers:|
TestService
|
In test.service.ts file
import { Injectable } from '@angular/core’;
@Injectable({
providedIn: 'root'
})
export class TestService {
printToConsole(arg: any){
console.log(arg)
}
constructor() { }
}
Now to call this method printToConsole we'll use Dependency Injection
Dependency Injection
We want to call printfoConsole method from AppComponent class
First - let us call the method by using instance
constructor(){
let svc=new TestService()
svc.printtoConsole("Manish")
}
But in this scenario we are binding TestService with AppComponent class
Second way - Dependeny Injection
The idea of dependency injection is that when you have a class that is dependent on
another class - you don't have that class create that instance. What you do instead
have the class declare its dependency and have that dependency injected.
All you need to do declare a dependency on other services is just to create
constructor arguments. Angular is going to look at the constructor and its arguments
and it is going to see if any of these arguments are @Injectable. If there are services
- angular is going to find that service (otherwise it will create one) and then it is going
to pass that into the constructor (when this component is being created)
In app.component.ts file
import { Component } from '@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.html’,
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(svc: TestService){
svc.printtoConsole("Manish")
}
title = 'third-project’;
}
Check it in browser console.
Now it is available till the constructor runs. We can store it in instance variable. A
shortcut for doing it.
import { Component } from '‘@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private svc:TestService
constructor(svc: TestService){
this.svc=svc;
svc.printTtoConsole("Manish")
}
title = 'third-project’;
}
Or a shortcut
import { Component } from '@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
‘private svc:TestService
constructor(private svc: TestService){
//this.svc=svc;
this.svc.printToConsole("Manish")
}
title = 'third-project’;
}
Service Injection Context
Difference between the components operate and the services operate in the context
of module. A component can be declared inside module, in which case the
component is only available to other components in the module. If you want to make
it available outside the module you need to mark it in export; you need to add
component in the exports and then other module needs it has to import. Ifa
component has to be used outside its module - 2 rules
1. Owning module needs to export it
2. Then the module thats trying to use it needs to import the module.
But in case of services it works differently.
In app.module.ts - TestService has been provided in App module. You have added it
in the providers section in the module. Now you can cdo dependency injection inside
app.component.ts. Now there is another component - view component in the same
project. Now what happens if we use dependency injection in
view-component.component.ts and get access to TestService
import { Component, Onlnit} from '@angular/core’;
import { TestService } from ‘src/app/test.service';
@Component({
selector: 'app-view-component,
templateUrl: './view-component.component.html’,
styleUrls: ['.view-component.component.css']
})
export class ViewComponentComponent implements Onlnit {
constructor(private svc: TestService) {
svc.printtoConsole("From view module")
}
ngOnInit(): void {
}
}
Now view.module.ts is not dependent on App module. It is other way round. The App
module imports the view module. So can the view component access the service
that is inside App component? 
We have seen it works.
How is it possible? It is possible because of the way services works in Angular.
Services are not restricted to the module that they are provided in. App module has
TestService in providers. In the case of a component (e.g.AppComponent) that
component is only available in the module. But i case of service (or providers)
Angular creates a common shared space for services. There is a common area that
contains all the services in your application that anybody cann add too. Let's suppos
you have 3 different modules (each having different providers). Those providers are
not restricted to that module. They become part of this common shared service
space and any other component that makes a dependency injection which declares
its dependency on any of the services is going to get the instance of that service. It
doesn't have to be part of the module. The shared service space is referred as
Injection context (Dependency Injection context). This list is available to all the
components in your application. This is the reason why when Angular CLI created
service it did not automatically added to any of the module. It did not Know where to
provide TestService.
REST with HttpClient
How co you make REST API call with Angular? There is a service called HttpClient.
In order to use that service import the module that the service comes with. The
module contains service and the providers section. So when you import that module
that service get added in injection context so that it is available to all your
components.
In app.module.ts
import { NgModule } from '@angular/core’;
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http’;
import { AppRoutingModule } from './app-routing. module’;
import { AppComponent } from './app.component;
import { TestService } from '/test.service';
import { ViewModule } from '/view/view.module’;
@NgModcule({
declarations: [
AppComponent
1
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
ViewModule
1,
providers: [TestService],
bootstrap: [AppComponent]
})
export class AppModule { }
Now in app.component.ts (we'll inject service HttpClient)
ngOnInit(}{
//let response =this. http.get(‘https://api.github.com/users/koushikkothagal’)
//Can't do since you get an async object and in Angular world it is called
Observable (earlier in Angular JS it was called promise)
}
In app.component.ts
import { HttpClient } from '‘@angular/common/http’;
import { Component } from '@angular/core’;
import { TestService } from './test.service';
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
‘private svc:TestService
constructor(private svc: TestService, private http:HttpClient){
//this.svc=svc;
this.svc.printToConsole("Manish")
}
ngOniInit(){
//let response =this. http.get(‘https://api.github.com/users/koushikkothagal’)
//Can't do since it is an async request
let obs=this.http.get(‘https://api.github.com/users/koushikkothagal’)
obs.subscribe(()=>console.log("Got the response"))
}
title = 'third-project’;
}
Check in browser
Change it to
obs.subscribe((response)=>console.log(response))
Github API access with username in form
Update the view component
In view-component.component.html file
User Name : <input type="text"><br>
<button>Search</button>
We need to bind the input to member variable and then bind search click to a
function
So
User Name : <input type="text" [(ngModel)]="UserName"><br>
<button>Search</button>
For this to work we need FormModule in our View Module. So in view.module.ts file
import { NgModule } from '@angular/core’;
import { CommonModule } from '@angular/common';
import { ViewComponentComponent } from
" view-component/view-component.component’;
import { FormsModule } from '@angular/forms';
@NgModcule({
declarations: [
ViewComponentComponent
1,
imports: [
CommonModule,
FormsModule
],
exports:[ViewComponentComponent]
})
export class ViewModule { }
Again in view-component.component.html file
User Name : <input type="text" [(ngModel)]="UserName"><br>
<button (click)="search()">Search</button>
Now in view-component.component.ts file
import { HttpClient } from '@angular/common/http';
import { Component, Onlnit } from ‘@angular/core’;
import { TestService } from ‘src/app/test.service';
@Component({
selector: 'app-view-component,
templateUrl: './view-component.component.html’,
styleUrls: ['.view-component.component.css']
})
export class ViewComponentComponent implements Onlnit {
userName: string=""
response: any;
constructor(private http: HttpClient) {
search(){
let obs=this.http.get(‘https://api.github.com/users/'+this.userName)
obs.subscribe((response)=>this.response=response)
console.log(this.response)
}
ngOnlnit(): void {
}
}
Remove Git API code from app.component.ts file
Check it in browser console
Now we want to print the result in browser
In view-component.component.html file
User Name : <input type="text" [(ngModel)]="UserName"><br>
<button (click)="search()">Search</button>
<br><br>
{{response. login}
Check it
(Ignore the errors in the browser console (it is because when the component loads
up initially it has a blank response (because userName is blanl)))
Again in view-component.component.html file
User Name : <input type="text" [(ngModel)]="UserName"><br>
<button (click)="search()">Search</button>
<br><br>
<p>Login Name : {{response.login}}</p>
<p>Number of repos : {{response.public_repos}}</p>
<p>Number of gists : {{response.public_gists}}</p>
<p>Number of followers : {{response.followers}}</p>
Check it
Now we don't want Login Name :,Number of repos,etc to be displayed (click
refresh) when there is no name. So use nglf
User Name : <input type="text" [(ngModel)]="UserName"><br>
<button (click)="search()">Search</button>
<br><br>
<div *nglf="response">
<p>Login Name : {{response.login}}</p>
<p>Number of repos : {{response.public_repos}}</p>
<p>Number of gists : {{response.public_gists}}</p>
<p>Number of followers : {{response.followers}}</p>
</div>
Check it. Now errors in browser console has gone.
Otherway to do it (apart from nglf (use 7?))
User Name : <input type="text" [(ngModel)]="UserName"><br>
<button (click)="search()">Search</button>
<br><br>
<p>Login Name: {{response?.login}}</p>
<p>Number of repos : {{response?.public_repos}}</p>
<p>Number of gists : {{response?.public_gists}}</p>
<p>Number of followers : {{response?.followers}}</p>
But in this case text is appearing. So use nglf
Building an Angular Application
Using ng serve we get a simple dev server. And it is very handy. You make a change
in codebase, it automatically updates it and it automatically refreshes your browser
By default we get hot reload in Angular. But when you'll be hosting this application,
you con't need it. This is a waste.
Secondly, when you create Angular application you are having a lot of code that
could be optimized (when you are hosting on server).
When you run ng serve command - Angular looks at your codebase and bundles up
all your module and it creates a local server. Now this is a development server. Now
how does it matter.
Open your browser inpector and come to Network tab and refresh the page again.
There are bunch of JS files that are loading. (runtime.js, styles.js, vendor.js). These
are all pretty big files. And they are not even minified. We need to minify these files.
If we want a simple component (three files) without any server side code, this is
something you can host and deploy on CDN and have the user loaded without
needing a server running at all times. This is static content. To generate this static
content of the project - ng build
ng build runs the Angular CLI which looks at your project and generates HTML, CSS
and JS into one folder and that is going to be independent of Angular CLI, Node
version. It is just static asset that you can deploy
A dist folder is created. And it again has a bunch of files in it that can be hosted. You
can deploy this folder into CDN
To do it install nom package
npm install http-server -g
http-server lets you to host a directory on your machine as if you are hosting it ona
CDN. You can access it locally.
To run it
http-server <dir name>
http-server dist/third-project
It is by default ng build --configuration production
It also creates hashes (e.g. main.#value). The reason being if you update a file and
build it again a new hash would be generated. So you cache your values on the
server. Knowing that when there is a new build you'll get a new file name (that's
referred to by index.html}. As long as you are not caching index.html it is going to
fetch these new file names. So you get latest build while leveraging caching.
Check it on browser
http://127.0.0.1 :8081/
and it runs without ng serve
So we are now running it without Angular. Check browser inspector. The message
which was appearing earlier (Angular is running in development mode.) has gone.
Check the Network Tab also and click runtime.js and the file is minified.
Project with routing
ng new fourth-project
Open in VS Code
Check in package.json - you have a dependency on router
Check in app.module.ts AppRoutingModule has been included
And you have a file app-routing.module.ts - Open it. It has a class
AppRoutingModule.
It has some constant called routes (which is an empty array (which is fo type
Routes). Routes is basically an array of Route class (position mouse array on
Routes)
It is for configuring your routes. And then you pass this configuration in
@NgModcule({
imports: [RouterModule.forRoot(routes)],
Now we want to create 2 routes.
Let us first create 2 components home and settings
ng g c home
ng gc settings
In your app.module.ts file both of them are imported
In app-routing.module.ts file
import { NgModule } from '@angular/core’;
import{ RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './nome/home.component'’;
import { SettingsComponent } from './settings/settings.component;
const routes: Routes = [
{path:'home' component:domeComponent},
{path:'settings' ,component:SettingsComponeni},
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Now in order to provide a window for angular to put component in the view - Go in
your app.component.html file and delete all lines except
<router-outlet></router-outlet>
This is required by Angular to know where to put the components
Check in browser
localhost:4200/home
localhost:4200/settings
Route Redirects and Wildcard
Setup a default route - so that when user is not entering the URL
It should automatically redirect to home
We want to make home as the default route and we also want to handle errors (if
somebody enters wrong URL)
One way is (in app-routing.module.ts file)
import { NgModule } from '@angular/core’;
import{ RouterModule, Routes } from '@angular/router’;
import { HomeComponent } from './home/home.component';
import { SettingsComponent } from '/settings/settings.component’;
const routes: Routes = [
{path: ", component:HomeComponent},
{path:'home' component:domeComponent},
{path:'settings' ,component:SettingsComponeni},
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Check in browser
So you can have multiple paths mapped to same component.
But we would like to do it with a redirect.
import
import
import
import
NgModule } from '@angular/core’;
RouterModule, Routes } from '@angular/router’;
HomeComponent } from './nome/home.component'’;
SettingsComponent } from './settings/settings.component;
“aa
const routes: Routes = [
{path: ", redirectTo:'/home',pathMatch:'full’},
{path:'home' component:domeComponent},
{path:'settings' ,component:SettingsComponeni},
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Check it.
This can also be used
{path: ", redirectTo:'/home',pathMatch:'prefix’},
Now for error handling. Specifying a component when a path doesn't exists.
e.g. localhost:4200/manish
It doesn't shows anything.
Check error in browser inspector.
We want to show error message by component when someone tries to access a
URL which doesn't exists.
Use wildcard
ng g c page-not-found
import { NgModule } from '@angular/core’;
import{ RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component'’;
import { PageNotFoundComponent } from
" /page-not-found/page-not-found.component'’;
import { SettingsComponent } from './settings/settings.component’;
const routes: Routes = [
{path: ", redirectTo:'/home',pathMatch:'full’},
{path:'home' component:domeComponent},
{path:'settings' ,component:SettingsComponeni},
{path: '**' component:PageNotFoundComponent}
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Check it
Configuring Child routes
You want a route resolution inside a route.
We want to configure settings/profile and settings/contact and this we want to do
within settings component. So profile and contact needed to be rendered in a small
window within settings.
In settings.component.html file
<h1>Settings Page</h1>
Check localhost:4200/settings
Now we want component to be rendered below this Settings Page header when we
enter settings/profile or settings/contact.
ng g c settings-profile
ng g c settings-contact
We want it to match to a sub component or sub route or child route.
Now in app-routing.module.ts file can we add path like
{path:'settings/profile',component:SettingsComponent},
Doing this will not give angular a clue that it is child route.
So to do it we need to add another property in settings url - children and its datatype
is again Route array. (Route array has aproperty called children and the value of that
is another Route array. You can specify an array of Route as children to an existing
Route. That's how you have child Route)
In app-routing.module.ts file
import { NgModule } from '@angular/core’;
import{ RouterModule, Routes } from '@angular/router’;
import { HomeComponent } from './nome/home.component'’;
import { PageNotFoundComponent } from
" /page-not-found/page-not-found.component'’;
import { SettingsContactComponent } from
" /settings-contact/settings-contact.component';
import { SettingsProfileComponent } from
./settings-profile/settings-profile.component’;
import { SettingsComponent } from './settings/settings.component;
const routes: Routes = [
{path: ", redirectTo:'/home',pathMatch:'full’},
{path:'home' component:domeComponent},
path:'settings’,
component:SettingsComponent,
children: [
{path:'profile’,component:SettingsProfileComponent},
{path:'contact',component:SettingsContactComponent},
]
},
{path: '**' component:PageNotFoundComponent}
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Now the point is where Angular is going to put this rendered component?
You have one router-outlet at application level (app.component.html). This is where
Settings component went. Now where the child is going to go in Settings component.
For it you have to create a router-outlet in Settings component as well. So in
settings.component.html file
<h1>Settings Page</h1>
<router-outlet></router-outlet>
This is where child of Settings component will get plugged in.
Check it with settings/profile and settings/contact
Now we want setting url default to profile
import { NgModule } from '@angular/core’;
import{ RouterModule, Routes } from '@angular/router’;
import { HomeComponent } from './nome/home.component'’;
import { PageNotFoundComponent } from
" /page-not-found/page-not-found.component'’;
import { SettingsContactComponent } from
" /settings-contact/settings-contact.component';
import { SettingsProfileComponent } from
./settings-profile/settings-profile.component’;
import { SettingsComponent } from '/settings/settings.component’;
const routes: Routes = [
{path: ", redirectTo:'/home',pathMatch:'full’},
{path:'home' component:domeComponent},
path:'settings’,
component:SettingsComponent,
children: [
{path: ", redirectTo:'profile’,pathMatch:"full’},
{path:'profile’,component:SettingsProfileComponent},
{path:'contact',component:SettingsContactComponent},
]
},
{path: '**' component:PageNotFoundComponent}
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Again one more (for settings/not found)
import { NgModule } from '@angular/core’;
import{ RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component'’;
import { PageNotFoundComponent } from
" /page-not-found/page-not-found.component'’;
import { SettingsContactComponent } from
" /settings-contact/settings-contact.component';
import { SettingsProfileComponent } from
./settings-profile/settings-profile.component’;
import { SettingsComponent } from '/settings/settings.component’;
const routes: Routes = [
{path: ", redirectTo:'/home',pathMatch:'full’},
{path:'home' component:domeComponent},
path:'settings’,
component:SettingsComponent,
children: [
{path: ", redirectTo:'profile’,pathMatch:"full’},
{path:'profile’,component:SettingsProfileComponent},
{path:'contact',component:SettingsContactComponent},
{path: '**' redirectTo:'profile’, pathMatch:'full'}
|
},
{path: '**' component:PageNotFoundComponent}
1;
@NgModcule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
For a wrong settings URL it will redirect it to profile page.
Showing Navigation for routes
In app.component.html
Check in browser
Now the problem is when you click these link it is doing full page refresh. Also check
it by going into browser inspector - network tab.
This is not we want. We ware building SPA.
The whole page is loading because when you do <a href=...It is actually instruction
for the browser to load the URL. But you don't want the browser to load the full page
URL. Now how to tell angular to change the route.
It can be done using routerLink directive.
<h1>My App</h1>
<a routerLink="home">Home</a>
<a routerLink="settings">Settings</a>
<router-outlet></router-outlet>
Now it works. It doesn't do a full page refresh.
Now same thing with class property resolution.
In app.component.ts file
import { Component } from '@angular/core’;
@Component({
selector: 'app-root’,
templateUrl: './app.component.html’,
styleUrls: ['./app.component.css']
})
export class AppComponent {
homeRoute="home"
settingsRoute="settings"
title = 'fourth-project'’;
}
And In app.component.html
<h1>My App</h1>
<a [routerLink]="homeRoute">Home</a>
<a [routerLink]="settingsRoute">Settings</a>
<router-outlet></router-outlet>
Another good way for it
In app.component.ts file
import { Component } from '@angular/core’;
@Component({
selector: 'app-root’,
templateUrl: './app.component.htm',
styleUrls: ['./app.component.css']
})
export class AppComponent {
homeRoute="home"
routes=[
{linkName: ‘Home’ url:'‘home’}},
{linkName: 'Settings',url:'settings'},
]
}
And In app.component.html
<h1>My App</h1>
<a *ngFor="let route of routes" [routerLink]="route.url">{{route.linkKName}}</a>
<router-outlet></router-outlet>
Check it
Now to add sub nav
In settings.component.html file
<h1>Settings Page</h1>
<a *ngFor="let route of routes" [routerLink]="route.url">{{route.linkKName}}</a>
<router-outlet></router-outlet>
And in settings.component.ts file
import { Component, Onlnit} from '@angular/core’;
@Component({
selector: 'app-settings’,
templateUrl: './settings.component.htm'’,
styleUrls: ['./settings.component.css']
})
export class SettingsComponent implements Onlnit {
routes=[
{linkName: 'Profile’,url:'profile’},
{linkName: ‘Contact Info',url:‘contact'’},
]
constructor() { }
ngOnInit(): void {
}
}
Check it
Angular Technologies
@ Angular
@ JavaScript
/ TypeScript
@ Angular CLI
@ Reactive programming, RxJS, Observables, operators
@ Jasmine, Karma
@ Redux, ngRx
HTML JS
Show current date and time
HTML
Add a div and paragraph
Add button
JS
Code to get date/time
Get the paragraph DOM element
Update value
Code function to handle
button click
Component based approach
Capstone ms2
header
header-section
<header-section></header-secttion>
main-section side-bar
header-section .
footer-section
<header-section></header-section>
<main-section></main-section>
<Side-bar></side-bar>
<footer-section></footer-section>
Capstone ms2
main-section Side-bar
header-section
footer-section
info-section details-panel
header main
/oN
summary
footer
details
sidebar
JN
nav updates
Root
component
pe Ne,
header main footer
/oN
summary details
sidebar
foN
nav updates
HTML
Add a div and paragraph
Add button
JS
Code to get date/time
Get the paragraph DOM element
Update value
Code function to handle
button click
date click
Root
component
fo
date click
AppComponent
HelloWorldComponent
HelloWorldComponent /|
Compute the
current date
date.component.html — DateComponent Class
Show the
computed date
export class DateComponent implements OnInit {
J
constructor() { }
neOnInit() {
}
|
}
Angular Routing
Routing
Routing
eK
Routing
Routing
Routing
Routing
Capstone ms2
URL based routing
foo.com/view1 foo.com/view2
URL based routing
index.html
foo.com/ ?
URL based routing
index.html
foo.com/view1
Component based routing
Capstone ms2
One component per view
Component 1 Component 2 Component 3
One root component per view
Component 1 Component 2 Component 3
One root component per view
Component 1 Component 2 Component 3
URL based routing
+~
Component based routing
Views URL Component
View 1
View 2
Views URL Component
View 1 foo.com/view1
View 2 foo.com/view2
Views
View 1
View 2
URL
foo.com/view1
foo.com/view2
Component
Component 1
Component 2
Routing in Angular
@ Define your route URLs
@ Create Angular components for each view (one for each
route)
@ Configure Angular to map route URLs to components
https://nodejs.org/en/
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
NVM installation link
https://github.com/nvm-sh/nvm
For mac
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
Copy the commands from above command
export NVM_DIR="$HOME/.nvm"
[ -s "BNVM_DIR/nvm.sh" ] && . "BNVM_DIR/nvm.sh" # This loads nvm
[ -s "BNVM_DIR/bash_completion" ] && . "BNVM_DIR/bash_completion" # This
loads nvm bash_completion
and put it in ~/.bash_profile
Close the terminal and open new terminal
nvm -v
If it doesn't runs
source ~/.bash_profile
Now come to Usage section of https://github.com/nvm-sh/nvm
and run
nvm install node
If you install older version like
nvm install 6.14.4
then node switches automatically to that version. Check it by
node -v
NVM for windows download
https://github.com/coreybutler/nvm-windows
REPL - Read Evaluate Print Loop
node
Node prompt lets you write JS code and execute it
243
vara
a=10
a
a*3
var b=a*4
b
For multiline commands
if(a>10){
console.log("Greater than 10")
}
To exit ctrl+c - ctrl+c or ctrl+d or .exit
After exiting memory gets cleared
vi one.js
console.log("Hello World");
node one
var a=10;
var b=20;
var c=a+b;
console.log(c};
Editor VSCode
Module - Every JS file is a module in itself.
Make a addjs file
function add(a,b)
return a+b;
console.log(add(1,2));
Make another file first.js
require('./add.js');
function greet(name){
console.log("Hello "+name);
}
greet("Manish");
require - is the way to import a module
Move require('./add.js'); at the end of file and run again
Now what if we want to call the add function in first.js
require('./add.js');
function greet(name){
console.log("Hello "+name);
}
greet("Manish");
add(3,4);
node first - will give an error - add is not defined
Node modules are encapsulated by default. So once require("./add.js") finishes - add
function is not available.
How do we do it?
In add.js
function add(a,b)
{
}
return a+b;
console.log(add(1 ,2));
module.exports=add;
and in first.js
var addFn= requie('./add.js’);
function greet(name){
console.log("Hello "+name);
}
greet("Manish");
console.log(addFn(3,4)):;
What if you have more functions to be exported?
In add.js
function add(a,b)
{
}
function subtract(a,b)
{
return a+b;
return a-b;
}
console.log(add(1 ,2));
module.exports={
add: add,
subtract: subtract
};
O
//module.exports={
// add,
// subtract
I};
//So this time we are exporting object
So in first.js
var operObj= requie('./add.js');
function greet(name){
console.log("Hello "+name);
}
greet("Manish");
console.log(operObj.add(3,4));
Another way to export is
In add.js
function add(a,b)
{
}
function subtract(a,b)
{
}
return a+b;
return a-b;
console.log(add(1 ,2));
module.exports.add=add;
module.exports.subtract=subtract;
Run it and check again
There is a shortcut code - instead of module.exports.add=add; write
exports.add=add;
(Actually nodejs is running var exports=module.exports; So exports is available as
an alias)
Another code for add.js
exports.add=(a,b)=>a+b; // Arrow function
and in first.js
var {add}= requie('./add.js'); //Using Destructuring
function greet(name){
console.log("Hello "+name);
}
greet("Manish");
console.log(add(3,4));
Require with node api
nodejs.org/api/index.htm!
Search for read
Click on the Reacline on left
Copy the line const reacdLine=require(‘readLine’)
Create a new file greet.js
Copy the usage sample
const readLine=require(‘readLine’)
const readline = require(‘readline’);
const rl = readline.createlnterface({
input: process.stdin,
output: process.stdout
});
rl.question(‘What do you think of Node.js? ', (answer) => {
/! TODO: Log the answer in a database
console.log( Thank you for your valuable feedback: ${answer}));
rl.close();
});
Change it to
const readline = require(‘readline’);
const rl = readline.createlnterface({
input: process.stdin,
output: process.stdout
});
rl.question(‘What is your name? ', (name)=>{
console.log( Hello {$name}
);
rl.close();
});
WAP to add 2 numbers
Writing user input to a file
nodejs.org/api/index.html - there is a FilSystem link
Click on fs.writeFile and check the documentation
Make a file greet-to-file.js
const fs=require(‘fs');
fs.writeFile(‘greeting.txt’,'Hello World',err=>{
console.log('Error occured’);
});
Check it.
Actually you should check
const fs=require(‘fs');
fs.writeFile(‘greeting.txt','Hello World’ ,err=>{
ifferr) {
console.log('Error occured’);
}
});
Another one with arguments
const fs=require(‘fs');
const writeGreetingToFile=(name)=>{
fs.writeFile(‘greeting.
txt’, Hello ${name} ,err=>{
if(err) {
console.log('Error occured’);
}
ys
}
writeGreeting ToFile('Manish’);
Take input from user and store it in a file
const fs=require(‘fs');
const readline = require(‘readline’);
const writeGreetingToFile=(name)=>{
fs.writeFile(‘greeting.
txt’, Hello ${name} ,err=>{
if(err) {
console.log('Error occured’);
const rl = readline.createlnterface({
input: process.stdin,
output: process.stdout
});
rl.question(‘What is your name? ', (name)=>{
/Iconsole.log( Hello {$name}
);
rl.close();
writeGreeting ToFile(name);
});
Making a project
npm -v
mkdir timezone
cd timezone
npm init
Is
Make index.js file
console.log(‘Hello World’);
To run
node index
Or (a common command)
In package.json "scripts" add
"start" :"node index.js",
Now run it with
npm start
npm test
You can create your own script like
"myscript":"Is"
You run it with
npm myscript — //It will fail
npm run myscript
We'll use moments - a tz utility
Open momenitjs.com
npm install moment
(it will download in your current folder)
In index.js file
let moment=require(‘moment'’)
console.log(moment().format('ddda’)
Run using
npm start
Now we con't want to share the downloaded libraries with others. We share the
project code. (Delete node_modules folder).
The other person will run npm install
Creating a command line utility
npm init
npm install moment
npm install moment-timezone
Make an index.js file
const moment=require(‘moment);
moment.tz.setDefault(‘America/Los_Angeles');
const targetTimezone="Europe/Paris";
console.log(moment().tz(targetTimezone).format());
/iconsole.log(-The time at the ${targetTimezone} is
${moment().tz(targetTimezone).format()}
);
Now we want to do it from command line arguments
node index.js "Asia/Kolkata"
But it doesn't take the arguments
The way to get to command line arguments is using an object called process.argv
which is available to Node
const moment=require(‘moment);
moment.tz.setDefault(‘America/Los_Angeles');
const targetTimezone="Europe/Paris";
console.log(process.argv);
console.log(-The time at the ${targetTimezone} is
${moment().tz(targetTimezone).format()}
);
node index.js "Asia/Kolkata"
const moment=require(‘moment);
moment.tz.setDefault(‘America/Los_Angeles');
let targetTimezone;
if(process.argv.length!=3)}{
console.log("Usage : node <script> <tz>");
}
else
{
}
//const targetTimezone="Europe/Paris";
//console.log(process.argv);
console.log(The time at the ${targetTimezone} is
${moment().tz(targetTimezone).format()}
);
targetTimezone=process.argv[2];
node index.js "Asia/Kolkata"
Callbacks in Node.js
Make a file file-api-.js
let fs=require(‘fs’);
//fs.writeFileSync(‘test.txt',,A sample text’);
//console.log(‘After file is written’);
fs.writeFile(‘test.txt’,"Text written async’ (err)=>{
console.log(‘After file is writtem’);
})
console.log(‘This should print after previous line’);
node file-api.js
Take 2 nos. from user and print their sum
Take 3 nos. from user and find out the greatest number
Basic
function abc(}{}
console.log(abc());
var fn=function (){
console.log("Sample output");
}
fn();
setTimeout(fn,5000);
function placeAnOrder(orderNumber)
{
console.log("Customer Order : ",orderNumber);
cookAndDeliverFood(function(){
console.log("Delivered Food Order : ",orderNumber);
});
}
function cookAndDeliverFood(callback){
setTimeout(callback,5000);
}
placeAnOrder(1)
placeAnOrder(2)
placeAnOrder(3);
placeAnOrder(4):;
(5)
(6)
(7)
placeAnOrder
placeAnOrder
placeAnOrder
Reference to an Object
var amit={
favFood: "DalChaval",
favMovie: "3 Idiots"
}
var person=amit;
person.favFood="Dosa";
console.log(amit.favFood);
this reference
var person={
printFirstName: function(){
console.log("Amit’);
console.log(this===person);
}
}
person.printFirstName();
//The default calling context is global
function sam(){
console.log("Naveen");
console.log(this===global);
}
sam();
Prototype
function User(){
this.name="""
this.life=100;
this.giveLife=function (targetPlayer){
targetPlayer.life+=1;
console.log(this.name +" give 1 life to "+targetPlayer.name);
}
}
var amit=new User();
var naveen=new User‘();
amit.name="Amit";
naveen.name="Naveen";
amit.giveLife(naveen);
console.log("Amit : "+amit.life);
console.log("Naveen : "+naveen life);
//Add function to all objects
User.prototype .uppercut=function(targetPlayer){
targetPlayer.life-=3;
console.log(this.name +" gave uppercut to "+targetPlayer.name);
}
naveen.uppercut(amit);
console.log("Amit : "+amit.life);
console.log("Naveen : "+naveen life);
//Add properties to all objects
User.prototype.magic=50;
console.log("Amit : "+amit.magic);
console.log("Naveen : "+naveen.magic);
Shared state of modules (Default behaviour of NodeJS - Any time you export an
Object from a module that object gets shared among every other modules)
Make movies.js
module.exports={
favMovies: ""
}
Make naveen.js
var movies=require("./movies");
movies.favMovie="3 Idiots";
console.log("Amit's favourite movie is : "+movies.favMovie);
Make amit.js
var movies=require("./movies");
console.log("Amit's favourite movie is : "+movies.favMovie);
Make app.js
require("./naveen.js");
require("./amit.js");
Object Factory
(Default behaviour of NodeJS - Any time you export an Object from a module that
object gets shared among every other modules. So anytime we want to create a new
object we actually need to export a function that creates a new Object. This is what
Object factory is - It is an Object which creates another Object)
In movie.js
module.exports=function(}{
return {
favMovie:
}
}
Now ian naveen.js
var movies=require("./movies");
var naveenMovies=movies();
naveenMovies.favMovie="3 Idiots";
console.log("Naveen's favourite movie is : "+naveenMovies.favMovie);
Now in amit.js
var movies=require("./movies");
var amitMovies=movies();
console.log("Amit's favourite movie is : "+amitMovies.favMovie);
Core Modules
var fs=require('fs');
fs.writeFileSync(“abc.txt","A sample text")|
console.log(fs.readFileSync("abc.txt").toString);
var path=require("path");
var abc="DesktopDataabc.txt";
console.log(path.normalize(abc);
console.log(path.dirname(abc);
console.log(path.baseame(abc});
console.log(path.extname(abc);
setinterval(function(){
console.log("Hello");
},200);
console.log(__ dirname);
console.log(__ pathname);
Basic Server
Make server.js
var http = require(‘http’);
function onRequest(request, response) {
console.log("A user made a request " + request.url);
response.writeHead(200, { "Content-Type": "text/plain" });
response.write("Hi user");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server is running...");
Simple Web File Server
Make index.html file
<h1>My Page</h1>
In server.js
var http = require(‘http’);
var fs=require('fs');
function send404Response(response){
response.writeHead(200, { "Content-Type": "text/plain" });
response.write("Error 404:Page not found");
response.end();
}
function onRequest(request, response) {
if(request.method=="GET" && request.url=="/"}{
response. .writeHead(200, { "Content-Type": "text/html" });
fs.createReadStream("./index.html").pipe(response);
jelse{
send404Response(response);
}
}
http.createServer(onRequest).listen(8888);
console.log("Server is running...");
Connect (Server Framework)(With this middleware you can stack the function calls)
npm install connect
In server.js
var connect = require(‘connect'’);
var http = require(‘http’);
var app=connect()};
http.createServer(app).listen(8888);
console.log("Server is running...");
Now
var connect = require(‘connect'’);
var http = require(‘http’);
var app=connect()};
function doFirst(request,response,next){
console.log("Hello");
}
app.use(doFirst)
http.createServer(app).listen(8888);
console.log("Server is running...");
With this middleware you can stack the function calls
var connect = require(‘connect'’);
var http = require(‘http’);
var app=connect()};
function doFirst(request,response,next){
console.log("Hello");
next();
}
function doSecond(request,response,next){
console.log("Bye");
next();
}
app.use(doFirst)
app.use(doSecond)
http.createServer(app) listen(8888);
console.log("Server is running...");
Remark next(} and check
var connect = require(‘connect'’);
var http = require(‘http’);
var app=connect()};
function doFirst(request,response,next){
console.log("Hello");
//next();
function doSecond(request,response,next){
console.log("Bye");
next();
app.use(doFirst)
app.use(doSecond)
http.createServer(app).listen(8888);
console.log("Server is running...");
var connect = require(‘connect'’);
var http = require(‘http’);
var app=connect()};
function profile(request,response){
console.log("User profile");
}
function forum(request,response){
console.log("User forum");
}
app.use("/profile" profile);
app.use("/forum",forum);
http.createServer(app).listen(8888);
console.log("Server is running...");
Template
PUG
index.pug file
html
head
title= title
body
hi= message
(Also show the difference of title = title)
index.js file
var express = require(‘express');
var app = express();
app.set('view engine',‘pug')
app.get(‘/’, function(req, res){
res.render(‘index', {
title: "My Page",
message:"A sample message"
});
});
app.listen(3000);
Show the generated page in Inspector
If you want to add doctype
Then do it with
title= abc
It will dissapear
Again do it with
title= "abc"
Then
p Asample paragraph
Show the difference with
p= A sample paragraph (Will give an error)
p = "A sample paragraph"
Then
a(href="https://nucleus.niituniversity.in/") NU Website
Now show the anchor tag within p tag (by indenting)
Then
ul
li Dosa
li Idli
li Parantha
Then put this ul tag in div tag
For form input element
input(name="fname", type="text", id="fn")
With placeholder
input(name="fname", type="text", id="fn" placeholder="First Name")
Then adding a label to it
label(for="fn") Enter Name
Show input for password
Now table
table
tr
td
label First Name
td
input(name="fn" id="fn")
tr
td
label Last Name
td
input(name="In",id="In")
Now form tag
form(method="post" action="get")
label(for="{n") Enter Name &nbsp;
input(name="fname", type="text", id="fn")
input(type="submit",value="Save")
Now CSS
In public folder make css folder and main.css file
h1{
color: red;
}
In head tag
link(rel="stylesheet" href="/static/css/main.css")
And in index.js file
app.use(/static',express.static(‘public’))
Now make js/main.js in public folder
alert("Hello");
And in index.pug
In head
script(src="/static/js/main.js")
Now extends layout
Make layout.pug in views folder
Cut the contents of index.pug and paste it in layout.pug
Now cut the form part of it
and write
block content (in line with html tag)
in layout.pug file
Now in index.js file
extends layout
block content
var ‘express'
//var bodyParser = require(‘body-parser);
//var multer = require(multer);
//var upload = multerQ;
var
‘/', function
‘form’
‘view engine’, 'pug'
//app.set(‘views’, './views');
// for parsing application/json
//fapp.use(express.jsonQ);
// for parsing application/xwww-
//form-urlencoded
// for parsing multipart/form-data
//fapp.use(upload.array();
//app.use(express.static(‘public’));
app ‘/', function(req, res
console req.body
res "recieved your request!"
app
var express = require(‘express’);
var bodyParser = require(‘body-parser’);
/var multer = require(multer’);
/var upload = multer();
var app = express();
app.get(’/', function(req, res){
res.render(‘form’);
});
app.set('view engine’, 'pug’);
/lapp.set(‘views’, './views');
// for parsing application/json
//app.use(bodyParser.json());
//app.use(express.json());
// for parsing application/xwww-
//app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.urlencoded({ extended: true }));
//form-urlencoded
// for parsing multipart/form-data
//app.use(upload.array()};
app.use(express.static(‘public’));
app.post('/', function(req, res){
console.log(req.body);
res.send("recieved your request!");
});
app.listen(3000):
The Components object is deprecated. It will soon be removed. - Due to Selenium
addon
Don't use : while printing variable content
"start": "nodemon -e js,pug",
app.use(bodyParser()); //Now deprecated
You now need to call the methods separately
app.use(bodyParser.urlencoded()};
app.use(bodyParser.json());
Cookies
var ‘express'
var app
app ‘/', function(reg, res
res ‘name’, ‘Manish’, {maxAge: ‘cookie set’): //Sets name =
express
//res.cookie(rememberme’, '1', { expires: new Date(Date.nowQ + 900000),
httpOnly: true });
app
To send multiple cookies
var ‘express'
var app
app ‘/', function(reg, res
res ‘name’, ‘Manish’, {maxAge:
res ‘mob' maxAge:
res ‘cookie set’); //Sets name = express
app.listen(3000
Retrieving cookies
var express = require(express'
var app = express
var cookieParser = require(‘cookie-parser’): //is required in retrieving cookies
app.use(cookieParser
//app.use(express.urlencoded({extended: true}))
app.get(/', function(req, res
res.cookie(‘name’, ‘Manish’
res.cookie(‘mob', 9015
res.send(‘cookie set’); //Sets name = express
app.get(/cook', function(reg, res
console.log(‘Cookies: ', reg.cookies
res.send(‘cookie in console’): //Sets name = express
app.listen(3000
Session
A session secret in connect is simply used to compute the hash. Without the string, access to
the session would essentially be "denied".
var express = require(express'
var cookieParser = require(‘cookie-parser’
var session = require(‘express-session'
var app = express
app.use(cookieParser
app.use(session
secret: "MySecret"
resave: true
saveUninitialized: true
app.get(/', function(req, res
"You visited this page " "times"
else
"Welcome to this page for the first time!"
mongod --dbpath ../data/db
curl -X PUT --data "name=Toy#20storyéyear=1995érating=8.5"
http://localhost:3000/movies/101
User authentication
npm init -y
npm i express berypt
npm i --save-dev nodemon
Make server,js file
In package.json file in scripts section
“devStart": "nodemon server.js",
On terminal
In server.js
const express=require('express’)
const app=express()
app. listen(3000)
This server doesn't do anything
npm run devStart
Add
const users=[]
app.get('/users',(req,res)=>{
res.json(users)
})
Install REST Client in VS Code (to make REST calls)
Make another file request.rest
GET http://localhost:3000/users
and click on Send Request
Now check by adding in users array
users=[{name: 'Manish’}]
Now
app.post('/users',(req,res)=>{
const user={name: req.body.name,password: req.body.password}
users.push(user)
res.status(201).send()
})
Now to use json
app.use(express.json())
This will allow application to allow JSON
In request.rest file
POST hittp://localhost:3000/users
Content-Type: application/json
{
"name": "Manish",
"password": "Abc"
}
Now the password is visible
And to make it hash
hash(salt+'password')
hash(salt2+'passworc’')
We want password to be hashed so even if someone gets access to db....
Now in server.|s
const berypt=require(‘bcrypt')
Now change app.post
app.post('/users' async (req,res)=>{
try{
const salt=await bcrypt.genSalt()
const hashedPassword=await bcrypt.hash(req.body.password,
salt)
console.log(salt)
console.log(hashedPassword)
const user={name: req.body.name,password: hashedPassword}
users.push(user)
res.status(201).send()
}
catch{
res.status(500).send()
}
})
See the salt and hashedPassword on server console
Now to reduce the code
app.post('/users' async (req,res)=>{
try{
//const salt=await bcrypt.genSalt()
const hashedPassword=await bcrypt.hash(req.body.password,10) //salt replaced y
10 (def value)
//console.log(salt)
//console.log(hashedPassword)
const user={name: req.body.name,password: hashedPassword}
users.push(user)
res.status(201).send()
catch{
res.status(500).send()
}
})
Now to login
In request.rest file copy paste POST request and
POST hitp://localhost:3000/users/login
Content-Type: application/json
{
"name": "Manish",
"password": "Abc"
}
Now create the route in server.js file
app.post('/users/login'
async (req,res)=>{
const user=users.find(user=>user.name=req.body.name)
if(user==null)
return res.status(400).send("Cannot find user")
try{
if(await bcrypt.compare(req.body.password,user.password)){
res.send("success")
}
else{
res.send("Unauthorized")
}
}catch{
res.status(500).send()
}
})
Now from request.rest file create the user using first post request
And then try login with different password
JWT
npm init -y
npm i express jsonwebtoken dotenv
dotenv file which is going to contain our secret tokens for JWT
Make .env file
npm i --save-dev nodemon
Make server,js file
In package.json file in scripts section
“devStart": "nodemon serverjs",
On terminal
npm run devStart
In server.js
const express=require(‘express')
const app=express()
app. listen(3000)
This server doesn't do anything
Now
const posts=[
{
username: ‘Manish’,
title: ‘one’
},
{
username: ‘Amit’,
title: 'two'
}
]
app.get('/posts',(req,res)=>{
res.json(posts)
})
Install REST Client in VS Code (to make REST calls)
Make another file requests.rest
GET hittp://localhost:3000/posts
and click on Send Request
Now we need to authenticate our request using JWT so that we don't let everyone
access the posts - only specific users, so
app.posi(‘/login' (req,res)=>{
//Authenticate User
})
To do authentication we want to use jsonwebtoken
And to do that we need to require the library
const jwt=require(‘jsonwebtoken')
app.use(express.json())
app.posi(‘/login' (req,res)=>{
//Authenticate User
const username=req.body.username
const user={name: username}
const access Token=jwt.sign(user,process.env.ACCESS TOKEN_SECRET)
res.json({access Token: access Token})
})
Now in terminal open node prompt
node
>require(‘crypto').randomBytes(64).toString(‘hex’)
and again
>require(‘crypto').randomBytes(64).toString(‘hex')
Copy the generated tokens in env file
ACCESS _TOKEN_SECRET=45102a2f8c44e202cdcc0648cdfb68ca6dc54879eca95
0e5fa431981e55a8b8491 dabe1 3313ef781 92c33bbd29a3ddc1 6688675f1f7a7851e5
e793ea7991ae88
REFRESH_TOKEN_SECRET=a2892c578591 2c42a509f8d43f231075a36201 aeb067
716d709ecb23ec04e7fccd47906e1 bceb26fc984b2b50ebe4eb6261 8346d264a9b70f
e786635788dede5
Now in requests. rest file
HHH
POST hitp://localhost:3000/login
Content-Type: application/json
{
}
It will show an error -s
Because we are not loading .env variables into our process.env
To do it add this line on top of server.js file
require(‘dotenv’).config()
"username": "Manish"
Now again send the POST request
This returns access token (which has no expiration date and user info saved in it).
So we can access any of our endpoints with the user info.
Now let's create a middleware which is going to authenticate our token
This token is going to come into header (authorization)
function authenticate Token(req,res,next){
const authHeader=req.headers['authorization’]
const token= authHeader && authHeader.split(’ ')[1]
if (token==null) res.sendStatus(401)
jwt.verify(token,process.env.ACCESS_TOKEN_SECRET
,(err,user)=>{
if(err) return res.sendStatus(403)
req.user=user
next()
})
}
Now change app.get(‘posts')
app.get(‘/posts’, authenticate
Token, (req,res)=>{
res.json(posts. filter(post=>post.username===req.user.name)) //It is only going
to return the post which the user has access to
})
In requests.rest file
GET hittp://localhost:3000/posts
Authorization: Bearer <token>
Now test it
Then login as Amit
To use them across many different servers
In package.json in start script
“devStart2": "nodemon server2.js",
Copy server.js into server2.js
and inserver2.js change port to 4000
In another prompt npm run devStart2
Now inrequests.rest file make a post request form server at port 3000 and copy the
key and use it in GET on server at port 4000
Now we can make authentication server different
Rename server2.js to authServer.js
In package.json file
instead of "devStart2": "nodemon server2.js"
“devStartAuth": "nodemon authServer.js"
and npm run devStartAuth
From server.js file remove login section (delete app.post(‘login’)
In authServer you can delete const posts array and app.get(‘posts') method
Right now token has no expiration date
The idea of REFRESH Token is that you save the token in the same spot and then
normal access token have short expiration date
So if someone gets your access token he has got the access for few minutes before
that access is revoked
and then user must use REFRESH Token to get a new token
And it also does have the same problem that your token gets stolen and someone
else can use to refresh your token
and that's where the idea of invalidating the REFRESH token is.
You can essentially create logout route which deletes a REFRESH token
So the reason for using REFRESH token is
1. So that user can invalidate
2. And to take all your authentication and authorization code and move it away from
normal server
https://www.youtube.com/watch?v=SnoAwLP 1a-0&list=PL4cUxeGkcC¥iqqESP8335
DA5cRFp8loyp
In Node Application, any async function accepts a callback as the last parameter and
a callback function accepts an error as the first parameter.
Callback Function
A callback function is a function (It can be any function Anonymous Function, Arrow
Function) passed into another function as an argument, which is then invoked inside
the outer function to complete some kind of routine or action.
function show() {
console.log("I am show Function");
function geeky(callback) { callback();
}
geeky(show)};
function show(a) {
console.log("I am show Function" + a);
}
function geeky(callback) { var a = 101; callback(a);
}
geeky(show)};
let x= function (}{
console.log(“Called from inside a function”)
}
let y=function(callback){
console.log(“do something”);
callback();
}
y(x)
let calc=function(num1 ,jnum2,calcType){
if (calcType==="add”)
return num1+num2;
}
else if(calcType==="multiply”)
{
}
return num1*num2;
console.log(calc(2,3,’add’));
console.log(calc(2,3,’multiply’));
let add=function(a,b){
return a+b;
}
let multiply=function(a,b){
return a*b;
let calc=function(num1 ,num2,callback}{
return callback(num1 ,num2);
}
console.log(calc(2,3,add));
Now try with multiply
Now add
let doWhatever=function(a,b){
console.log(’ Numbers are ${a} and ${b}>);
}
and then
console.log(calc(2,3,doWhatever)):
Now | don’t have to define function outside
console.log(calc(2,3,function(a,b){return a-b;}))
Now to check if the argument is function
let calc=function(num1 ,num2,callback}{
if(typeof callback==="function”)
return callback(num1 ,num2);
}
var myArr=[{
num: 5,
str: “apple”
},
{
num: 7,
str: “cabbage”
},
{
num: 1,
str: ‘ban’
};
myArr.sort(function(val1 ,val2){
if(val1 .str>val2.str)
return -1;
else
return 1;
});
console.log(myArr);
var fs=require("fs")
var file="data.txt"
fs.exists(file function (exists){
if(exists}{
fs.stat(file function(err,stat){
if(err) throw err;
if(stat.isFile(}){
fs.readFile
(file, "utf8" function(err,data){
if(err} throw err;
console.log(data);
Or
var fs=require("fs")
var file="data.txt"
function readFile(err,data){
if (err) throw err;
console.log(data);
}
function status(err,stat){
if (err) throw err;
if(stat.isFile(}){
fs.readFile(file
,"utf8" read File);
}
}
function fileExists(exists){
if(exists)
fs.stat(file status);
}
fs.exists(file, fileExists);
app.use(bodyParser.urlencoded({ extended: false }));
If extended is false, you can not post "nested object"
person[name] = 'cw'
/! Nested Object = { person: { name: cw
} }
If extended is true, you can do whatever way that you like.
When extended property is set to true, the URL-encoded data will be parsed with
the qs library.
On the contrary,
when extended property is set to false, the URL-encoded data will instead be
parsed with the querystring library.
The differences between parsing with “qs library’ vs “querystring library”
qs library allows you to create a nested object from your query string.
var qs = require("qs")
var result = qs.parse("person[name]=bobby&person[age]=3")
console.log(result) //{ person: { name: ‘bobby’, age: '3' } }
query-string library does not support creating a nested object from your query
string.
var queryString = require("query-string")
var result = queryString.parse("person[name]=bobby&person[age]=3")
console.log(result) //{ 'person[age]': '3', 'person[name]': 'bobby' }
qs library will not filter out '?' from the query string.
var qs = require("qs")
var result = qs.parse("?a=b")
console.log(result) //{ '?a': 'b'}
query-string library will filter out '?' from the query string.
var queryString = require("query-string")
var result = queryString.parse("?a=b")
console.log(result) //{ a: 'b'}
Many of us that have been using the Node/Express Framework have been used to
installing another piece of middleware in order for us to be able to read the “body” of
an incoming JSON object. This piece of middleware was called body-parser and
used to not be part of the Express framework. The good news is that as of Express
version 4.16+, their own body-parser implementation is now included in the default
Express package so there is no need for you to download another dependency.
npm uninstall body-parser
Jenkins Continuous Build System
Continuous Integration
= Continuous integration systems are avital part of any Agile team because they help enforce
the ideals of Agile development
= Jenkins, acontinuous build tool, enables teams to focus antheir work by automating the build,
artifact management, and deployment processes
= Jenkins’ core functionality and flexibility allow it to fit in avariety of environments and can
help streamline the development process for all stakeholders involved
CI Defined
“Continuous Integration is asoftware development practice where members of ateam integrate
their work frequently, usually each person integrates at least daily - leadingto multiple
integrations per day. Eachintegration 1s verified by an automated build (including test) to detect
integration errors asquickly as possible’— Martin Fowler
ob Continuous Integration
Code is pulled over
every commit made in
the source code
BEE ——
| Every change made in
the source code is
Commit changes to build continuously
the source code
en
CI— What does ttreallymean?
= At aregular frequency (ideally at every commit), the system 1s:
= Integrated
= All changes up until that point are combined into the project
» Built
= The code is compiled into an executable or package
= Tested
= Automated test suites are run
Archived
= Versioned and stored so it can be distributed asis, if desired
Deployed
= Loaded onto asystem where the developers can interact with it
CI -Workflow
tle Continuous
Ie esstre ws Build System Executable/ Repository
Package
Artifact
Testing Results
Deployment
Developers
CI— Benefits
= Immediate bug detection
= Nointegration step in the lifecycle
= Adeployable system at any given point
= Record ofevolution ofthe project
CI— Thetools
= Code Repositories
=» SVN, Mercurial, Git
= Continuous Build Systems
# Jenkins, Bamboo, Cruise Control
= Test Frameworks
= =JUnit,Cucumber, CppUnit
= Artifact Repositories
= Nexus,Arttfactory,Archiva
Jenkins
Jenkins is an open source automation tool written in Java with plugins built for
Continuous Integration purpose.
Jenkins is used to build and test your software projects continuously making it
easier for developers to integrate changes to the project, and making it easier for
users to obtain a fresh build.
With Jenkins, organizations can accelerate the software development process
through automation.
Jenkins integrates development life-cycle processes of all kinds, including build,
document, test, package, stage, deploy, static analysis and much more.
Jenkins
2005 - Hudson wasfirst release by Kohsuke Kawaguchi dSun
Microsystems
2010— Oracle bought Sun Microsystems
Due to anaming dispute, Hudson was renamed to Jenkins
= Oracle continued development of Hudson (as abranch of the
original)
Javabased Continuous Build System
Runsin servlet container
= ~~Glassfish, Tomcat
Supported by over 400 plugins
= SCM.Testing, Notifications, Reporting, Artifact Saving, Triggers,
External Integration
What can Jenkinsdo?
= Generate test reports
= Integrate with many different Version Control Systems
= Pushto various artifact repositories
= Deploys directly to production or test environments
= Notify stakeholders of build status
How Jenkins works Setup
When setting up aproject in Jenkins, out of the box youheavethe following general options:
= Associating with aversion control server
= Triggering builds
Polling, Periodic, Building based on other projects
= Execution of shell scripts, bashscripts, Ant targets, and Maven targets
= Artifact archival
= Publish JUnit test results and Javadocs
= Email notifications
Asstated earlier, plugins expand the functionality even further
a
Jenkins Work Flow
Clone Mount | / Run  Pull build
repository in Workspace as——+ container environment
Workspace volume  / image
| Build | | Test | !
Po Workspace
| Build artifacts | Test results | ;
f — 
| Dispose 
 container /
4
Enhancing Jenkins
= Jenkins plugin system can enable a wide range of features including (but certainly not
limited to)
» SCM
= Mercurial, Git, Subversion
" Testing
= Selenium,Windmill,TestLink
= Notifications
# IRC,Twitter, Jabber
= Reporting
= Doxygen, PMD, Findbugs
= Artifact Saving
» Artifactory, Amazon $3, SCP
» Triggers
= Jabber, Directory Watchers
= External Integration
= GitHub, Bugzilla, JIRA
= And most importantly — The CI Game
= Apoints based game where developers compete against each other to
develop the most stable, well- tested code
Who uses Jenkins?
Linked{
i).
GAGEx)
SAIL x Ween
BOEING mozilla
FOUNDATION
Tying it into Agile
For an Agile team, Jenkins provides everything needed for a
robust continuous build system
‘Jenkins supports Agile principles by constantly providing
access to working copies of software
Jenkins’ extensibility allows the system to adapt to many
different pre-existing environments
Nu
wN
>
Installation of Jenkins
Download the latest stable Jenkins WAR file to an appropriate directory on your machine.
Open up a terminal/command prompt window to the download directory.
Run the command java -jar jenkins. war.
Browse to http://localhost:8080 and wait until the Unlock Jenkins page appears.
Continue on with the Post-installation setup wizard below.
You can change the port by specifying the --httpPort option
java -jar jenkins.war --httpPort=9090
Jenkins GUI Configurations
To use and configure Jenkins, visit the following address in your browser
http://y our-ip-address: 8080
You will be surprised to see its welcome screen where you will be able to configure its
different parameters for your system.
€ Jenkins
Jenkins + ENABLE AUTO REFRESH
e New Item fad description
& Feope Welcome to Jenkins!
Build History
Please Create new jobs to get started.
é Manage Jenkins
A Credentials
Build Queue a
No builds in the queue.
Build Executor Status =
1 Idle
2 Idle —
Installation on Ubuntu
Install Java Version 8 — Jenkins is a Java based application, hence Java is a must.
sudo yum install java-1.8.0-openjdk
Download Jenkins war File — This war is required to install Jenkins.
weet http://updates.jenkins-ci.org/download/war/2.7.3/jenkins.war
apt-get install Jenkins
(~ )
THE BASICS OF SETTING UP A JENKINS MASTER SERVER
Discover, Install and Manage Plugins
Jenkins has hundreds of useful plugins. Plugins will eliminate the need to create custom
scripting to solve common problems with minimal pain.
1.Navigate to Jenkins Web Interface > Login as Admin > Manage Jenkins > Manage
Plugins > Available (Tab)
Select checkbox for all the plugins you want to install
Select "Download now and install after restart" at the bottom of the page.
2. After Jenkins finishes restarting, the installed plugins will appear under Manage Plugins >
Installed (Tab)
Here are a few Jenkins plugin recommendations:
Git - allows you to integrate GitHub to clone repository
GitHub Pull Request Builder - builds pull requests in GitHub and reports results
Swarm - enables slaves to auto-discover nearby Jenkins master and join it automatically
Sauce OnDemand - allows you to integrate Sauce Labs Selenium testing with Jenkins
Pipeline - suite of plugins that lets you orchestrate automation, simple or complex
Slack - allows posting of build notifications to a Slack channel
Thinbackup - simply backs up the global and job-specific configurations
Ne yy,
a
As an admin of Jenkins, the Configure System page is a critical configuration section.
This page represents a variety of sections, each correlating to a different configuration
area from generic Jenkins settings, defining global environment variables, and most
installed plugins are configured on this page.
Steps
Navigate to Jenkins Web Interface > Login as Admin > Manage Jenkins >
Configure System
Configure the root directory for workspace and build record.
Configure System Settings
Home directory /opt/jenkins
WIGIKEpAES Tatot DanSesory ${JENKINS_ HOME}workspace/${ITEM_FULLNAME}
Build Record Root Directory ${ITEM_ROOTDIRYbuilds
JDK
JDK installations
Ant
Ant installations
JDK
Name OpenJDK Version 7
#) Install automatically @
Install from java.sun.com
Version | Java SE Development Kit 7u79 r
“| | agree to the Java SE Development Kit License Agreement
© Installing JDK requires Oracle account. Please enter your username/ password
Oe)em eae) se
Bre) yim)
Add Installer +
Add JDK
List of JDK installations on this system
Ant
Name Apache
#) Install automatically @
Install from Apache
Version| 1.9.6 ¥
a
Configure Global Settings
Straight out of the box Jenkins will allow anyone to run anything as a user of Jenkins
along with admin permissions, which is bad. I suggest enabling Lightweight Directory
Access Protocol (LDAP), wich allows you to use corporate service. Users can log into
Jenkins with their usual company login credentials.
Navigate to Jenkins Web Interface > Login as Admin > Manage Jenkins > Configure
Global Security
Select checkbox to enable security.
Set TCP port for JNLP slave agents to 9000.
Select LDAP from the Access Control (Security Realm) section and enter your LDAP
server address:
(— Continue..
pees Contra Security Realm
Delegate
10 serviet container
Gitnub Authentication
Plugin
Jenkins’
own user database
© Lorp
Sener
Waps /mycompany
5490
© Syntax of server field is SERVER or SERVER: PORT of idaps J/SERVER|:PORT]
1.Select matrix-based security from the Access Control (Authorization) section
2.Select the checkbox for Prevent Cross Site Request Forgery Exploits, and Enable
Slave --> Master Access Control
Create New Job
Step 1 — Go to the Jenkins dashboard and Click on New Item
1 Dashboard Penkins] =
=_ ae localhost: 2080), enkine Op) =
& Jenkins a
when Kins moan sarees
‘at New Hem acd dascipbon
MB People Welcome to Jenkins!
= Build History
yo Manage Jenkine | Fisss= create mew pobes to get started.
a. Credeniiale:
Baa uae
Rio builds in the queue
Gull
Executor
Sia iue.
1 kile
2 kobe
Pegs gececmted: Set 10 SNE TA RET AP) eb
wer, 1S
yy,
Step 2 — In the next screen, enter the Item name, in this case we have named it
Helloworld. Choose the “Freestyle project option’
Step 3 — We need to specify the location of files which need to be built. Click on the
Git option and enter the URL of the local git repository. If it is local repository then
mention local repository folder path.
Step 4 — Now go to the Build section and click on Add build step — Execute
Windows batch command
Step 5 — In the command window, enter the commands which you want to execute
and then click on the Save button.
Step 6 — Once saved, you can click on the Build Now option to see if you have
successfully defined the job.
Jenkins Distributed Architecture
Jenkins uses a Master-Slave architecture to manage distributed builds. In this
architecture, Master and Slave communicate through TCP/IP protocol.
Jenkins Master
Your main Jenkins server is the Master. The Master’s job is to handle:
= Scheduling build jobs.
= Dispatching builds to the slaves for the actual execution.
= Monitor the slaves (possibly taking them online and offline as required).
=" Recording and presenting the build results.
= A Master instance of Jenkins can also execute build jobs directly.
Jenkins Slave
A Slave is a Java executable that runs on a remote machine. Following are the
characteristics of Jenkins Slaves:
It hears requests from the Jenkins Master instance.
Slaves can run on a variety of operating systems.
The job of a Slave is to do as they are told to, which involves executing build jobs
dispatched by the Master.
You can configure a project to always run on a particular Slave machine, or a particular
type of Slave machine, or simply let Jenkins pick the next available Slave.
Jenkins Master will distribute its workload to the Slaves
Neate ete &
Jenkins Slave
yr
Jenkins Slaves are generally required to provide the desired environment.
It works on the basis of requests received from Jenkins Master.
>
Now let us look at an example in which Jenkins is used for testing in different environments
like: Ubuntu, MAC, Windows etc.
The diagram below represents the same:
Code commit
triggers
Continuous
Integration
Jenkins Server (Master)
GitHub repository
TCP/IP TCP/IP TCP/IP
atta diab aerate arava aia
Slave Slave yr W a) cE,
Ay & sa
The following functions are performed in the above image:
Jenkins checks the Git repository at periodic intervals for any changes made in the source code.
Each builds requires a different testing environment which is not possible for a single Jenkins
server. In order to perform testing in different environments Jenkins uses various Slaves as
shown in the diagram.
Jenkins Master requests these Slaves to perform testing and to generate test reports.
yy,
References
= Continuous Integration — Martin Fowler
= http://www.martinfowler.com/articles/continuousIntegration.
html
=# Hudson
= http://hudson-ci.org/
= Hudson Continuous Integration Server
= http://www.code-
magazine.com/articleprint.aspx?quickid=090607 1 &printmode=true
= The Hudson Book
= http://www.eclipse.ore/hudson/the-hudson-book/book-hudson.
pdf
= Jenkins
= https://wiki.jenkins-ci.org
= Monkey Image
= http://corrines-cormer2006. blogspot.com/2011/09/freebie-monday_26.html
= What is Continuous Integration
= http://confluence.public.thoughtworks.oreg/display/CCNET/Whattis+Continuous
» +Integration
Types of Jenkins Projects
simple, single tasks whole delivery cycle
e.g. run tests e.g. test | build | .. like pipeline
for a single br 1 for m
@ Jenkins
Jenkins + Credentials + System
4 Back to credential domains
@= Add Credentials
Global credentials (unrestricted) +
Kind | Username
with password
Scope | Gilobal (Jenkins, nodes, items, all child items, etc) ]@
*
Username
& ®
Password ) @
Credential Scopes
System == Only available on Jenkins server
NOT for Jenkins jobs
Global mn Everywhere accessible
es LL
Jenkins + Credentials + System + Global credentials (unrestricted)
4# Back to credential domains her Username with password
en me ey
@= Add Credentials a
*
Lelia od at
Pacerfe ude tielt eS 6
Certificate
® @
Username & Password
Certificate
Secret File
@ Jenkins
Jenkins » Credentials » System + Global credentials (unrestricted) »
* Back to credential domains ina ec es)
@= Add Credentials Perea : 7 @
tee
X.509 Client Certificate es ©
eateries
Username & Password New types
based on plugins
Certificate
Secret File
> Jenkins
ikins Credentials System Global credentials (unrestricted)
Back to credential domains Kind Username with password
» Add Credentials Scope Global (Jenkins, nodes, items, all child items, etc)
Username global
Password...
sad glob
Description
ID = Reference for your credentials
@ Jenkins search
Jenkins Credentials System Global credentials (unrestricted)
> Back to credential domains
@= Add Credentials oy Global credentials (unrestricted)
Credentials that should be available irrespective of domain specification to requirements matching.
Name Kind Descripti
a globai/****** Username with password
Icon: SML
@ Jenkins
Jenkins Credentials System
+ Back to credential domains
@= Add Credentials
Global credentials (unrestricted)
Kind Username with password
Scope System (Jenkins and nodes onty)
Username system
Password ||.
” system
Description
a search
Jenkins Credentials System Global credentiais (unrestricted)
* Back to Sredential domains
@ Add Credentials fy Global credentials (unrestricted)
Credentials that should be available irrespective of domain specification to requirements matching.
Name Kind Descripti
A global"***"" Username with password
A ser Username with password
Icon: SML
@ Jenkins
Jenkins my-pipeline
# Up
WA, Status
% Configure
f@ Scan Multibranch Pipeline Log
Qe Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
7 Build History
‘1. Project Relationship
= Check File Fingerprint
2 Rename
oO Pipeline Syntax
A Credentials
Be Now vi
Build Queue
No builds in the queue.
(~-) my-pipeline
This folder is empty
There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects
in branches that contain recognizable projects. Pipeline Branch projects support building branches within a
repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This file
should contain a valid Jenkins Pipeline. See also: Creating Multibranch Projects.
Configure
the project for a buildable repository or re-index branches if the repository has since been configured.
@ Jenkins
Jenkins my-pipeline
f Ue
. Status
Z Configure
§@ Scan Multibranch Pipeline Log
GS Multibranch Pipeline Events
(x) Delete Multibranch Pipeline
& People
@ Build History
. Project Relationship
$= Check File Fingerprint
2 Rename
0 Pipeline Syntax
A Credentials
Da Now Vi
Build Queue
No builds in the queue
esp my-pipeline
This folder is empty
There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects
in branches that contain recognizable projects. Pipeline Branch projects support building branches within a
Credential Scopes
System == Only available on Jenkins server
LOR Me te)ae Cal diate)
Global == Everywhere accessible
@ Jenkins
Jankins my-pipeline Credentials
# Up
O. Status
# Configure
§@ Scan Multibranch Pipeline Log
Multibranch Pipeline Events
© Delete Multibranch Pipeline
a People
“= Bulld History
“A. Project Relationship
4— Check File Fingerprint
‘> Rename
oO Pipeline Syntax
A. cr
a Folder
fi New View
Bu il helbbhti
A Credentials
ar P Store |
A, 4 Jenkins
lcoon: SML
Stores scoped to my-pipeline
P Store |
Qe y-nineline (global)
Stores from parent
P Store |
2 Jenkins (global)
(global)
Domain
global
ID
Domains
Domains
seeeee
@ Jenkins
Jenkins » my-pipeline + Credentials
Up
(. Status
Z Configure
§@ Scan Multibranch Pipeline Log
Project
A Credentials
T P Store | Domain ID
Credential Scopes
=— Limited to project, ONLY with
multibranch pipeline
x Configure
Ba Scan Multibranch Pipeline Log
oS Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
“& Build History
O, Project Relationship
4= Check File Fingerprint
—
a Rename
oO Pipeline Syntax
a Credentials
| Folggr
fi New View
ie P Store | Domain
A, | sentins (global)
Icon: SML
Stores scoped to my-pipeline
P Store |
[A m-ripwiine i& (global)
Stores from parent
P Store |
G senkins és (global)
K Configure
@ Scan Multibranch Pipeline Log
& Multibranch Pipeline Events
© Delete Multibranch Pipeline
&, People
> Build History
OX Project Relationship
4— Check File Fingerprint
2 Rename
0 Pipeline Syntax
A. Credentials
7 P Store |
| .S & Jenkins (global)
Icon: SML
Stores scoped to my-pipeline
?P Store
|
[Qi m-nipeline i (global)
Stores from parent
Bp Stare
|
enables to organize build jobs in folders __,..1,.
Domain
Saale
Jenkins my-pipeline Credentials
# Back to credential domains
@= Add Credentials
Folder Global credentials (unrestricted)
Kind Username with password
Username riappiceine
Password eeererereee
2 my-pipeling
Description
Ea,
@ Jenkins are
Jenkins my-pipeige - Credentials Folder Global credentials (unrestricted)
> Back to credential domains
@= Add Credentials ey Global credentials (unrestricted)
Credentials that should be available irrespective of domain specification to requirements matching.
Name Kind Description
a my-pineling/****** Username with password 2
icon: SML
@ Jenkins
Jenkins + my-pipeline Credentials
® Up ‘
OX Status @. Credentials
#. Configure
§@ Scan Multibranch Pipeline Log  : eens ovine = =
£2 Muttibranch Pipeline Events a 4 — (global) gobel global
i) Delete Multibranch Pipeline A A my-pipeline * (global) my-pipeline my-pipeline******
& People Icon: SML
ee Sule Hietory Stores scoped to my-pipeline
. Project Relationship
Pp Store | Domains
>) Check File Fingerprint
a 4 my-pinaline wi (global)
we Rename
oO Pipeline Syntax Stores from parent
A. Credentials P Store | Samus
4 Folder
z Jenkins ith (global)
fm New View
Build Queue =
Cereb it
Jenkins my-pipeline Credentials
# Up
 Status
#. Configure
la Scan Multibranch Pipeline Log
Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
“> Build History
, Project Relationship
4 Check File Fingerprint
“= Rename
oO Pipeline Syntax
i Credentials
q Folder
[i New View
Build Queve
No builds in the queue.
A. Credentials
Tr, Pp Store | Domain
A 4 enking (global) iobal
.. BB ~-nineline (global) trrlpipeline
Icon: SML
Stores scoped to my-pipeline
P Store |
A my-pipeline wh (global)
Stesattonmmarscs
» System credential NOT accessible here!
Q enkins i (global)
Domains
Domains
global/**"**
my-pipeline/**"""""
@ Jenkins Qsoarch
Jenkins All
Enter an item name
test!
This is the central feature of Jenkins. Jenkins will build your project, combining any SCM with any build system, and this can be even used for
something other than software build
Pipeline
 r / Orchestrates long-running activities that can span multiple build agents. Suitable for building pipelines (formerly known as workflows) and/or
organizing complex activities that do not easily fit in free-style job type.
_ Multi-configuration project
es | Suitable for projects that need a large number of different configurations, such as testing on multiple environments, platform-specific builds, etc.
Folder
Creates a container that stores nested items in it. Useful for grouping things together. Unlike view, which is just a filter, a folder creates a separate
" famespace, so you can have multiple things of the same name as long as they are in different folders.
» GitHub Organization
PMMA Srans a GitHih amanization far user acenunt for all rannsitarias matchinn same definad markers
Jenkins + All
Multi-configuration project
Suitable for projects that need a large number of different configurations, such as testing on multiple environments, platform-specific builds, etc.
)
Folder
Creates
a container that stores nested items in it. Useful for grouping things together. Unlike view, which is just
a filter, a folder creates
a separate
namespace, so you can have multiple things of the same name as long as they are in different folders.
GitHub Organization
» Scans a GitHub organization (or user account) for all repositories matching some defined markers.
GitHub Organization
» Scans a GitHub organization (or user account) for all repositories matching some defined markers.
Multibranch Pipeline
/ Creates a set of Pipeline projects according to detected branches in one SCM repository.
If you want to create a new item from other existing, you can use this option:
eo Copy from | Type to autocomplete
Jenkins » test »
# Up
O Status
#. Configure
a Scan Multibranch Pipeline Log
GE Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
@ Build History
OA, Project Relationship
4%) Check File Fingerprint
> Rename
oO Pipeline Syntax
Srey
fi New View
This folder is empty
There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects
in branches that contain recognizable projects. Pipeline Branch projects support building branches within a
repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This file
should contain a valid Jenkins Pipeline. See also: Creating Multibranch Projects.
Configure the project for a buildable repository or re-index branches if the repository has since been configured.
@ Jenkins
Credentials
Jenkins test
# Up
OL Status
#. Configure
§@ Scan Multibranch Pipeline Log
Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
> Build History
. Project Relationship
4>) Check File Fingerprint
2 Rename
© Pipeline Syntax
“A. Credentials
P
& @ er
Icon: SML
Store |
Stores scoped to test
Pp
Q xs
Store |
Stores from parent
P
4 Jenkins
Store |
i& (global)
i& (global)
(global)
Domain
global
Domains
Domains
- first syntax
Cg
node {
// groovy script]
}
Y dev / Jenkinsfile
pipeline {
Tey ULC) MARE
agent any
- Groovy TEL stages { - easier to get started,
PTET Ry stage("build”) { NEUE Ci
LT steps {
- difficult to sta .
Y dev / Jenkinsfile
bi peline {
- first syntax SHAE ECL
agent any
e PAY PTT i) stages { = easier to get started,
stage("build") { but not that powerful
Woman
nuwhWwne
steps { Sie CHES AiG
Mase ,
}
}
|
Y dev / Jenkinsfile
pipeline {
agent any
stages {
stage("build") f{
steps {
}
phde {
// groovy script
¥Y dev / Jenkinsfile
kbipeline {
agent any
stageC("build") f{
1
2
3
4
5 stages {
6
7
8
steps {
}
node {
// groovy script
}
Y dev / Jenkinsfile = a
SM TAM Gn ea ay
pipeline {
I eT CRC
agent any|
stages {
stage("build") {
steps {
}
node {
// groovy script
}
Y dev / Jenkinsfile “ ~
MAT Mea ie aa
pipeline {
me Me Ca
agent any
stages { Se TM mmm Te Mer dbs
stage("build") f
steps {
}
}
ae
}
node {
// groovy script
}
Y dev / Jenkinsfile Pt -
- “pipeline” must be top-level
pipeline {
me TM) CRTC
agent any
stages: 1 SCC TMC mM MT hy
stage("build") {
steps { = ae eT and “steps”
}
node {
// groovy script
}
Y dev / Jenkinsfile fs Select
a template type
1 pipeline {
2
3 agent any
4
5 stages {
6
7 stageC("build") {
8
9 steps {
10
11 }
12 }
13
14 stage("test") {
15
16 steps {
17
18 }
19 }
20
21 stage("deployf') {
22
23 steps { I
24
25 }
F OUev f/f JENKLINSTLLe w Select
a template type
1
2
3
4
5
6
7
8
ts]
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
22
PR
pipeline {
agent any
stages {
stageC"build") {
steps {
}
}
stage("test") {
steps {
}
}
stage("deploy") {
steps {
}
Nn
@
Ydev / Jenkinsfile FS Selecta template type ~
1
2
3
4
5
6
7
8
te)
10
11
12
13
14
15
16
LZ
18
19
20
21
22
23
24
25
26
27
pipeline {
agent any
stages {
stage("build") {
steps {
echo ‘building the application...‘
}
}
stage("test") {
steps {
echo 'testing the application..."
}
}
stage("deploy") {
steps {
echo 'deplying the application...'
}
i
Lo
ig
20
21
23
24
25
26
27
28
29
}
stage("deploy") {
steps {
}
echo 'deplying the application...
|
Commit message Add Jenkinsfile
Target Branch dev
Orel tial moral
laren
»
4
nl
a
"|
You pushed
to dev just now
& Jenkins
Jenkins my-pipeline
® Up
A. Status
7 Configure
(&) Scan Muttibranch @speline Now
| Scan Multibranch Pipeline Log
cS Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
~ Build History
A, Project Relationship
&= Check File Fingerprint
“@ Rename
©) Pipeline Syntax
@. Credentials
| Mmy-pipeline
This folder is empty
There are no branches found thal contain buildable projects. Jenkins automatically builds and manages projects
in branches that contain recognizable projects. Pipeline Branch projects support building branches within a
repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This {ile
should contain a valid Jenking Pipeling. See also: Creating Multibranch Projects
Configure the project for a buildable repository or re-index branches if the repository has since been configured
Sol ehi ts
JO@NKING my-pipeline
® Up
QL Status
7 Configure
& Scan Multipranch Pipeline Now
td Sq Done. PELO9
oe Multibranch Pipeline Events
© Delete Multibranch Pipeline
& People
@ Build History
A. Project Relationship
4= Check File Fingerprint
“= Rename
© Pipeline Syntax
&. Credentials
-~. my-pipeline
This folder is empty
There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects
in branches that contain recognizable projects. Pipeline Branch projects support building branches within a
repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This file
Should contain a valid Jenkins Pipeline. See also: Creating Multibraneh Projects.
Conhgure
the project for a buildable repository or re-index branches if the repository has since been configured
Jenkins + my-pipeline » Scan Multibranch Pipeline
aH Configure
(2) Scan Multibranch Pipeline Now
§@ Scan Multibranch Pipeline Log
© View as plain text
a Multibranch Pipeline Events
© Delete Muttibranch Pipeline
& People
‘> Build History
QO, Project Relationship
4>) Check File Fingerprint
in Rename
© Pipeline Syntax
” Credentials
fi New View
Build Queue
Started by user jenkins
[Fri Feb 07 05:34:12 UTC 2020] Starting branch indexing...
> git --version # timeout=10
using GIT_ASKPASS to set credentials
> git ls-remote --symref -- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git # timeout=.
> git rev-parse --is-inside-work-tree # timeout=10
Setting origin to https://gitlab.com/nanuchi/techwor]d-js-docker-demo-app.git
> git config remote.origin.url https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git # timeor
Fetching & pruning origin...
Listing remote references...
> git config --get remote.origin.url # timeout=10
> git --version # timeout=10
using GIT_ASKPASS to set credentials
> git ls-remote -h -- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git # timeout=10
Fetching upstream changes from origin
> git config --get remote.origin.url # timeout=10
using GIT_ASKPASS to set credentials
> git fetch --tags --progress --prune -- origin +refs/heads/*:refs/remotes/origin/* # timeout=10
Checking branches...
Checking branch master
*Jenkinsfile’ not found
Does not meet criteria
Checking branch feature-one
“Jenkinsfile’ not found
Does not meet criteria
Checking branch dev
‘Jenkinsfile’ found
Ses SSS
> git rev-parse --is-inside-work-tree # |
Ge Multibranch Pipeline Events Setting origin to https://gitlab.com/nanu:
> git config remote.origin.url https://q,
© Delete Multibranch Pipeline Fetching & pruning origin...
Listing remote references...
a, People > git config --get remote.origin.url # t:
> git --version # timeout=10
—s ‘i
wt Build History using GIT ASKPASS to set credentials
O Project Relationship > git ls-remote -h -- https://gitlab.com
Fetching upstream changes from origin
4= Check File Fingerprint > git config --get remote.origin.url # t.
-_ using GIT_ASKPASS to set credentials
= Rename > git fetch --tags --progress --prune --
Checking branches...
0 Pipeline Syntax Checking branch master
f . ‘Jenkinsfile’ not found
* STATE Does not meet criteria
Ga New View Checking branch feature-one
‘Jenkinsfile’ not found
Build Queue a Checking branch dev
No builds in the queue. Met criteria
Processed 4 branches
Build Executor Status = [Fri Feb 07 05:34:15 UTC 2020] Finished b:
Finished: SUCCESS
Gi search
@ Jenkins
Jenkins my-pipeline
# Up
t A, Status
Z Configure
&) Scan Multibranch Pipeline Now
§@ Scan Multibranch Pipeline Log
Multibranch Pipeline Events
© Delete Multibranch Pipeline
&, People
@ Build History
(. Project Relationship
4>) Check File Fingerprint
- Rename
oO Pipeline Syntax
A. Credentials
(. my-pipeline
-
abt
Branches (1)
s
@
Icon: SML
Ww
4
Name |
cu,”
Last Success
21 sec
- #1
Last Failure Last
NIA 205
Legend fj Atom
feed forall [J Atom feed for
@ Jenkins
Jenkins my-pipeline dev
® Up
. Status
~~ Changes
©) Build Now
¥% View Configuration
. Full Stage View
© Pipeline Syntax
.) Build History trend ==
find
@ #1 Feb 7, 2020 5:34 AM
Atom feed for all E Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
Stage View
2g Recent Changes
eet
Feb 07
06:34
Declarative:
Checkout SCM
16s
16s
build
50ms
test
44ms
Qi search
deploy
30ms
30ms
| @ Jenkins
Jenkins my-pipeline dev
® Up
O. Status
= Changes
) Build Now
tt View Configuration
. Full Stage View
©) Pipeline Syntax
_) Build History trend =
find
ou Feb 7, 2020 5:34 AM
Atom feed for all BY Atom feed for failures
Qisearch
Pipeline dev
Full project name: my-pipeline/dev
preerry
> A Recent Changes
Stage View
Declarative:
Checkout SCI . build test deploy
165 50ms 44ms 30ms
ei : 16s 50ms 44ms 30ms
06:34 -
@ Jenkins
Jenkins my-pipeline dev
Up
. Status
“= Changes
©) Build Now
Fs View Configuration
‘2, Full Stage View
© Pipeline Syntax
) Build History trend ==
find
w@ #1 Feb 7, 2020 5:34 AM
Atom feed for all F) Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
Rik
2 Recent Changes
——n
Stage View
Declarative: Success test deplo
Checkout SCM
ad
168 44ms 30ms
Feb 07 16s " a
06:34
Mines
ali nde
Stage Logs (build)
©Print Message — building the application... (self time 4ms)
building the application...
testing the application...
hk
@ Jenkins
Jenkins my-pipeline dev
% Up
O. Status
> Changes
© Build Now
tt View Configuration
OX Full Stage View
© Pipeline Syntax
Build History
find
eu Feb 7, 2020 5:34 AM
Atom feed for all ©) Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
= Recent Changes
ee
Stage View
Feb 07
06:34
Permalinks
Success
Jf
|
16s
build
50ms
test
44ms
44ms
or
‘A search
deploy
30ms
30ms
Stage Logs (Declarative: Checkout SCM)
© Check out from version control (self time 16s)
using credential demo-app-git-credentials
Cloning the remote Git repository
Cloning with configured refspecs honoured and without tags
Cloning repository https://qitlab. com/nanuchi/techword-js-docker-demo~app.git
> git init /var/jenkins_home/workspace/my-pipeline_dev # timeout=10
Fetching upstream changes from https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git
> git —-version # timeout=10
using GIT_AYKPASS to set credentials
> git fetch --no-tags --progress -- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git
+refs/heads/*:refs/remotes/origin/* # timeout=10
> git config remote.origin.url https://gitlab. com/nanuchi/techworld-js-docker-demo-app.git # tim
eout=10
> git config —add remote.origin. fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
> git config remote.origin.url https://git lab. com/nanuchi/techworld-js—docker-demo-app.git # tim
eout=10
Fetching without tags
Fetching upstream changes from https://gitlab.com/nanuchi/techword-js-docker-demo-app.git
using GIT_ASKPASS to set credentials
> git fetch —no-tags —progress —- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git
__
Qa search
Jenkins my-pipeline
# Up
. Status
Z Configure
@) Scan Multibranch Pipeline Now
§@ Scan Multibranch Pipeline Log
Multibranch Pipeline Events
& Delete Multibranch Pipeline
&} People
> Build History
. Project Relationship
4— Check File Fingerprint
= Rename
oO Pipeline Syntax
@. Credentials
(~)) my-pipeline
wk
Branches (1)
s Ww
¥ ,
Icon: SML
Name |
dev
Last Success
1 min 11 sec
- #71
Last Failure Li
N/A 2
Legend jj Atom feed for all Gj Atom feed for
Cc @ localhost
Jenkins » my-pipeline
General Branch Sources Build Configuration Scan Multibranch Pipeline Triggers Orphaned Item Strategy Health metrics
Properties Pipeline Libraries Pipeline Model Definition
Branch Sources
Git
Project Repository https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git ®
Credentials nn_janashia@yahoo.com/*****" 4 @» Add + ®
Behaviours Discover branches
Filter by name (with regular expression)
Regular expression “devimasterlfeature.*S ®
Add ~
Property strategy All branches get the same properties
ar
@ Jenkins
Jenkins my-pipeline dev
® Up
(OQ. Status
"> Changes
&) Build Now
es View Configuration
. Full Stage View
© Pipeline Syntax
-) Build History trend =
find
i #1 Feb 7, 2020 5:34 AM
Atom feed for all Fj Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
snot
e Recent Changes
: J
Stage View
Decidrative:
Checkout SCM
16s
Feb 07 . 1 6s
06:34
Permalinks
build
50ms
test
44ms
44ms
QA search
deploy
30ms
30ms
Test changes in a Jenkinsfile
—
| @ Jenkins Qa search
Jenkins my-pipeline
# Up
O. Status
Z Configure
&) Scan Multibranch Pipeline Now
§@ Scan Multibranch Pipeline Log
G Multibranch Pipeline Events
© Delete Multibranch Pipeline
&, People
“> Build History
©. Project Relationship
4>) Check File Fingerprint
= Rename
oO Pipeline Syntax
a Credentials
(-<) my-pipeline
ae
Branches (1)
s WwW
¥ -)
Icon: SML
Name | Last Success
5 min 31 sec
- #1
Last Failure Li
N/A 2
Legend {J Atom feed forall J Atom feed for
a
~~ om
iv
@ The file has been successfully created.
(2) Jenkinsfile 464 Bytes [6
Adjust Jenkinsfile
pipeline {
agent any
stages { PTET
IN I
stage("build") {
@ steps {
ho ‘building the applicat
° , SS en ee arte Ch
} -
@ tea TTL
stage("test") {
@ Jenkins search
Jenkins my-pipeline dev
#® Up . '
Pipeline dev
. Status
a Full project name: my-pipeline/dev
Changes
a
@) Build Now a Recent Changes
amen
es View Configuration
O. Full Stage View Stage View
© Pipeline Syntax
Declarative:
Checkout SCM build test deploy
-) Build History trend =
165 50ms 44ms 30ms
i el
find ' ' i
eu Feb §, 020 5:54 AM © €
Feb 07
Atom feed for all 5) Atom feed for failures obe4
=
=>
=|
fe
fs
5
30ms
Permalinks
@ Jenkins Q search
Jenkins my-pipeline dev #1
# Back to Project
OQ, Status @ Build #1 (Feb 7, 2020 5:34:15 AM)
- Changes
£@ Console Output
> Edit Build information a Branch indexing
© Delete build #1" Revision: a7f8 1ded96a13e1606bb72c085e4d6118bdde1
ad
« dev
@ Git Build Data ® git
GJ No Tags
@ Restart from Stage
© &pplay
~ Pipeline Steps
fi Workspaces
rs Jenkins
Qa search
Jenkins my-pipeline dev #1 Replay
® Back to Project
Replay #1
©, Status
*
Pee Allows you to replay a Pipeline build with a modified script. If any Load steps were run, you can also modify the scripts they loaded.
= Changes
Main Script l~ pipeline {
[3 Console Output 2
— 3 agent any
Edit Build Information 4
5° stages {
© Delete build ‘#1’ 6
7- stage("“build") {
} Git Build Data 8
9 steps {
GJ No Tags 10 echo ‘building the application...’
11 }
@ Restart from Stage 12 }
13
a Replay 14- stage("test") {
15
Pipeline Steps ns
Pipeline Syntax
[i Workspaces
gz Jenkins Qisearch
Jenkins my-pipeline dev #1 Replay
> Back to Project
Replay #1
Allows you to replay a Pipeline build with a modified script. If any load steps were run, you can also modify the scripts they loaded.
.
‘A. Status
> Changes
Main Script l= pipeline {
§@ Console Output ;
— 3 agent any
ea Edit Build Information 4
5° stages {
©& Delete build #1" 6
7+ stage("build") {
} Git Build Data 8
9- steps { I
Gl No Tags 10~ script {
11 |
@ Restart from Stage 12 }
13 }
& Replay 14 }
15
Pipeline Steps oe
Pipeline Syntax
(} Workspaces
ay J e nki beh)
Q search
Jenkins my-pipeline dev #1 Replay
# Back to Project
Replay #1
. Status
a Allows you to replay a Pipeline build with a modified script. If any Load steps were run, you can also modify the scripts they loaded.
we Changes
Main Script 6
wf Console Output 7> stage("build”) {
8
> Edit Build Information 9~ steps. {
= 10 echo ‘building the application...'
© Delete build #1" 11
12 ~ script {
} Git Build Data 13 def test = 2+ 2> 37? ‘cool’ : 'not cool"
14 echo test
GJ No Tags 15 }
16 }
® Restart from Stage 17 }
18
ad Replay 19 = stage("test") {
20
Pipeline Steps aaa ctone_f
Pipeline Syntax
fi Workspaces
@ Jenkins
Jenkins my-pipeline dev
# Up
. Status
“> Changes
© Build Now
t View Configuration
Full Stage View h
© Pipeline Syntax
-) Build History trend <=
find
@ #1 Feb 7, 2020 5:34 AM
Atom feed for all ©) Atom feed for failures
-—
=
Pipeline dev
Full project name: my-pipeline/dev
‘auououse
= Recent Changes
—
Stage View
Feb 07
06:46
Feb 07
06:34
Declarative:
Checkout SCM
165
16s
build
50ms
test
44ms
AQ search
deploy
30ms
30ms
@ Jenkins
Jenkins my-pipeline dev
# Up
. Status
2 Changes
) Build Now
tt View Configuration
, Full Stage View
© Pipeline Syntax
+ Build History trend =
find
@ #2 Feb 7, 2020 5:48 AM
w@ #1 Fab 7, 2020 5:47 AM
Atom feed for all 3} Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
‘ouout
2g" Recent Changes
ot
Stage View
Feb 07
06:48
eB Feb 07
06:47
Declarative: Success
Checkout SCM
6s | io ea |
1 J
gg
870ms 7ims
tis 4oms
test
32ms
Qa search
deploy
3ims
32ms
Stage Logs (build)
© Print Message — building the application... (self time 4ms)
building the application...
k
© Print
Message
— cool (self time 3ms)
Capstone ms2
©) Restart from stage
ripeine aev
Full project name: my-pipeline/dev
OY Status
7 Changes
saaaaeti
§@) Build Now [aa Recent Changes
tt View Configuration
OY Full Stage View Stage View
oO Pipeline Syntax
Declarative:
ct SCM build test deploy
Build History trend =
Average stage times: 6s 55ms sems aims
find x (Average full runtime: 8s .?_—_—==[[—_u—= « . — = a
en Feb 7, 2020 5:48 AM ee.
| Feb 07 No
en Feb 7, 2020 5:47 AM = Changes 870ms 71ims 34ms 31ms
| =e o--
| _feed for failures @& ——
a Console Output | Febo7 | C = 1is 40ms 3ims 32ms
> Edit Build Information a
© Delete build ‘#2
>} Git Build Data Permalinks
Gl No Tags * Last build (#2), 13 ms ago
* Last sable bulk (41). 1 min0 sec 90
Restart from Stage
fi @ Pore tom rege | * (cicaeieitieris abel alindeemaamy
OY Status
a Changes
® Build Now
tt View Configuration
O, Full Stage View
oO Pipeline Syntax
_) Build History
find
@ #2
eH
Feb 7, 2020 5:48 AM
Feb 7, 2020 5:47 AM
oa
-_ a
fa Console Output
_ j
= Edit Build Information
8 Delete build '#2”
eh Git Build Data
Gl No Tags
feed
for failures
ripeine aev
Full project name: my-pipeline/dev
[aif Reson Chances
Stage View
Average stage times:
(Average full run time: ~8s)
No
| Feb 07
| Changes
06:48
Permalinks
Last build (#2), 13 ms ago
! build (#4
870ms
lis
build
55ms
7ims
40ms
32ms
34ms.
aims.
deploy
31ims
31ims
32ms
jak ee a Ee Lae ee
min
* iaukone tik banalete 1 min
0 sec aao
Jenkins » my-pipeline +» dev +» #2 » Restart from Stage
4 Back to Project
OY Status
= Changes
Restart #2 from Stage
ae ULe re
ct aan
deploy
{@ Console Output
2a Edit Build Information
© Delete build ‘#2’
©} Git Build Data
tJ No Tags
@ Restart from Stage
@ Replay
- 2 Pineline Stance
Jenkins
# Up
» my-pipeline +» dev +
OY Status
> Changes
® Build Now
Fed View Configuration
OY Full Stage View
© Pipeline Syntax
_) Build History trend =
find x
eu Feb 7, 2020 5:50 AM
@ #2 Feb 7, 2020 5:48 AM
oH Feb 7, 2020 5:47 AM
3) Atom feed for all J Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
ada
=a? Recent Changes
a
Stage View
Feb 07 No
| Changes
06:50
Febo7 | No
| Changes
06:48 |
Febo7 | Ne
i nn-a?T
Declarative:
Checkout SCM
4s
858ms
870ms
lis
build
55ms
7ims
40ms
32ms
34ms
gims
deploy
34ms
39ms
aims
32ms
Jenkins
& Up
Q Status
7 Changes
my-pipeline +» dev
& Build Now
& View Configuration
OY Full Stage View
o Pipeline Syntax
_» Build History
find
@#8
ef
eH
Feb 7, 2020 5:50 AM
Feb 7, 2020 5:48 AM
Feb 7, 2020 5:47 AM
fS) Atom feed for all Ey Atom feed for failures
Pipeline dev
Full project name: my-pipeline/dev
didenooe
ag Recent Changes
bee
Stage View
Feb 07
06:50
Feb 07
06:48
Febo7 | No
N6:AT
Skips the other stages
Declarative:
Checkout SCM
4s
858ms
870ms
lis
build
55ms
71ms
40ms
test
32ms
34ms
Sims
deploy
34ms
39ms
3ims
32ms

More Related Content

PPTX
Sharing Data Between Angular Components
PDF
Hidden Docs in Angular
PDF
Angular 2.0 - What to expect
PPTX
Typescript barcelona
PDF
Angular 2 binding
PDF
Angular 2 introduction
PDF
A Tour of Building Web Applications with R Shiny
PDF
The Django Book chapter 4 templates (supplement)
Sharing Data Between Angular Components
Hidden Docs in Angular
Angular 2.0 - What to expect
Typescript barcelona
Angular 2 binding
Angular 2 introduction
A Tour of Building Web Applications with R Shiny
The Django Book chapter 4 templates (supplement)

What's hot (20)

PPTX
Применение паттерна Page Object для автоматизации веб сервисов
PDF
The Ring programming language version 1.2 book - Part 27 of 84
PPT
Visual studio 2008
PPT
WPF Controls
DOCX
Angular Interview Questions & Answers
PPT
Silverlight 2 for Developers - TechEd New Zealand 2008
PPTX
Data annotation validation (ASP.net)
PDF
4Developers: Dominik Przybysz- Message Brokers
PPT
GWT Training - Session 2/3
PPT
GWT Training - Session 3/3
PDF
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
PDF
Exploring Angular 2 - Episode 2
PPTX
Angular 2 KTS
PDF
Pragmatic functional refactoring with java 8 (1)
PDF
An introduction to Angular2
PDF
Introduction to Polymer and Firebase - Simon Gauvin
DOCX
C# 6.0
PDF
Angular.js Primer in Aalto University
PDF
Flutter State Management Using GetX.pdf
PDF
Domain Driven Design and Hexagonal Architecture with Rails
Применение паттерна Page Object для автоматизации веб сервисов
The Ring programming language version 1.2 book - Part 27 of 84
Visual studio 2008
WPF Controls
Angular Interview Questions & Answers
Silverlight 2 for Developers - TechEd New Zealand 2008
Data annotation validation (ASP.net)
4Developers: Dominik Przybysz- Message Brokers
GWT Training - Session 2/3
GWT Training - Session 3/3
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
Exploring Angular 2 - Episode 2
Angular 2 KTS
Pragmatic functional refactoring with java 8 (1)
An introduction to Angular2
Introduction to Polymer and Firebase - Simon Gauvin
C# 6.0
Angular.js Primer in Aalto University
Flutter State Management Using GetX.pdf
Domain Driven Design and Hexagonal Architecture with Rails
Ad

Similar to Capstone ms2 (20)

PPTX
Angular Framework ppt for beginners and advanced
PDF
Exploring Angular 2 - Episode 1
PDF
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
PDF
Angular JS2 Training Session #2
PPTX
Angular2 + rxjs
PDF
Interoperable Component Patterns
PDF
.NET Portfolio
PPTX
Angularjs2 presentation
PPTX
passDataB_wComponentInAngular.pptx
PPTX
AngularJs Workshop SDP December 28th 2014
PDF
Angular 2 - The Next Framework
PDF
Understanding router state in angular 7 passing data through angular router s...
PDF
Building an Android app with Jetpack Compose and Firebase
PDF
Angular - Chapter 4 - Data and Event Handling
DOCX
Django wrapper
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
PPTX
angularJs Workshop
PDF
Murach : How to work with session state and cookies
Angular Framework ppt for beginners and advanced
Exploring Angular 2 - Episode 1
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Angular JS2 Training Session #2
Angular2 + rxjs
Interoperable Component Patterns
.NET Portfolio
Angularjs2 presentation
passDataB_wComponentInAngular.pptx
AngularJs Workshop SDP December 28th 2014
Angular 2 - The Next Framework
Understanding router state in angular 7 passing data through angular router s...
Building an Android app with Jetpack Compose and Firebase
Angular - Chapter 4 - Data and Event Handling
Django wrapper
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
angularJs Workshop
Murach : How to work with session state and cookies
Ad

Recently uploaded (20)

PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
PDF
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PDF
STATICS OF THE RIGID BODIES Hibbelers.pdf
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
PDF
Pre independence Education in Inndia.pdf
PPTX
Lesson notes of climatology university.
PDF
01-Introduction-to-Information-Management.pdf
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PPTX
master seminar digital applications in india
PDF
Insiders guide to clinical Medicine.pdf
PDF
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PDF
TR - Agricultural Crops Production NC III.pdf
PDF
Complications of Minimal Access Surgery at WLH
PPTX
Cell Structure & Organelles in detailed.
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PDF
Microbial disease of the cardiovascular and lymphatic systems
PPTX
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
PDF
O7-L3 Supply Chain Operations - ICLT Program
PPTX
Institutional Correction lecture only . . .
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
STATICS OF THE RIGID BODIES Hibbelers.pdf
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Pre independence Education in Inndia.pdf
Lesson notes of climatology university.
01-Introduction-to-Information-Management.pdf
2.FourierTransform-ShortQuestionswithAnswers.pdf
master seminar digital applications in india
Insiders guide to clinical Medicine.pdf
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
TR - Agricultural Crops Production NC III.pdf
Complications of Minimal Access Surgery at WLH
Cell Structure & Organelles in detailed.
Supply Chain Operations Speaking Notes -ICLT Program
Renaissance Architecture: A Journey from Faith to Humanism
Microbial disease of the cardiovascular and lymphatic systems
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
O7-L3 Supply Chain Operations - ICLT Program
Institutional Correction lecture only . . .

Capstone ms2

  • 1. Installation NodeJS VS Code Angular CLI (https://angular.io/cli) npm install -g @angular/cli (@abc/xyz is called "scoped" package name. These names are of the format @group/package) ng version ng new first-project Is cd first-project Is Open project in VS Code To run the project ng serve On browser http://localhost:4200/ Check index.html file app-root component is available in app folder app.component.ts, app.component.html and app.component.css files provide functionality and look and feel of app component A component is a combination of view and backing logic app.component.ts provides backing logic, app.component.html and app.component.css files providelook and feel of app component Make a change in index.html and check in browser Make a change in app.component.ts title = 'My first-project'’; Dynamic logic will come from type script file Make a change in app.component.css h1{ color: red; } app.component.spec.ts is for test case Delete all the content in app.component.html and save Creating your first component In terminal stop the server (Ctrl C) Create a new component ng generate component hello-world Check in VS Code Check hello-world.component.ts You have a selector for it which is going to instantiate this component. You can use the selector in html markup of a component and then it is going to call it as a child component Open app.component.html file Run the server ng serve We have created a component and use it in another component You can use hello-world component multiple times and it is going to create those many instances
  • 2. Check in browser Anatomy of a component We want to make a date component which prints current date Open terminal in VS Code ng generate component date Open date-component.ts and see the selector In app.component.html <app-date></app-date> Check it Every angular component is mainly a typescript class. Think of the HTML and CSS as just extra "attachments" to the main typescript file. So angular CLI creates a class for a component. Or in order to create a component you have to create a typescript class (if you were to do it yourself). After you have created the class you need to register the class as an angular componert. It is done with @Component annotation. You can try changing selector template Url attributes and also do required changes and can try it out(In date.component.ts file ) Binding data from component class Create a member variable in DateComponent class message: string = "hello"; In date.component.html file {{message}} Check it in browser Now instead of "hello" text change it to new Date() message: string = new Date().toDateString(); (or toString) In date.component.html file <div> <p>The date is:</p> <p> {{message}} </p> </div> Data binding in Angular refers to binding the data in the component instance to the HTML template. Any change to the data get automatically updated in the view. Right now it is one way flow of data - from component to html Data binding and async We want to constantly update time export class DateComponent implements Onlnit { dateMessage: string; constructor() { let currentDate=new Date() this.dateMessage=currentDate.toDateString()+' '+currentDate.toLocaleTimeString() } ngOnInit(): void { } }
  • 3. And in html file <div> <p>The date is:</p> <p> {{dateMessage}} </p> </div> Right now the new Date object is created in constructor. So, it currently only executes when the page is loaded which causes the component instance to be created. In oorder to update time we need to create new Date object every second. So we'll use setlnterval in constructor export class DateComponent implements Onlnit { dateMessage: string | undefined; constructor() { setinterval(() => { let currentDate = new Date() this.dateMessage = currentDate.toDateString() + '' + currentDate.toLocaleTimeString() }, 1000) } ngOnInit(): void { } } Check in browser Template Interpolation Text interpolation lets you incorporate dynamic string values into your HTML templates.Interpolation refers to embedding expressions into marked up text. By default, interpolation uses the double curly braces {{ and }} as delimiters. {{dateMessage}}-double curly brackets trigger angular to do string interpolation In html {{1+1}} Define a num variable in class {{num*2}} Now double curly brackets with function call import { Component, Onlnit } from ‘@angular/core’; @Component({ selector: 'app-date’, templateUrl: './date.component.htm’, styleUrls: ['./date.component.css'] }) export class DateComponent implements Onlnit { dateMessage: string | undefined; num: number=1 2; constructor() { setinterval(() => { let currentDate = new Date()
  • 4. this.dateMessage = currentDate.toDateString() + '' + currentDate.toLocaleTimeString() }, 1000) } ngOnlnit(): void { add(a:number,b:number}{ return a+b } } And in html file <div> <p>The date is:</p> <p> {{dateMessage}} </p> {{num*2}}<br> {{add(num,2)}} </div> Check it this is required in class but not in html import { Component, Onlnit } from '@angular/core’; @Component({ selector: 'app-date’, templateUrl: './date.component.htm’, styleUrls: ['./date.component.css'] }) export class DateComponent implements Onlnit { dateMessage: string | undefined; num: number=1 2; constructor() { setinterval(() => { let currentDate = new Date() this.dateMessage = currentDate.toDateString() + '' + currentDate.toLocaleTimeString() }, 1000) } ngOnlnit(): void { add(a:number,b:number}{
  • 5. return a+b } someMeth() //here this.add(this.num,2) } } Looping with ngFor Make a new seconc-project Clear code from app.component.htm| and delete line title = 'app'; in app.component.ts Check with ng serve Stop the server and create new component address card ng generate component address-card It get registered in app.module.ts To check address-card component works, from address-card.component.ts file take the selector and use it in app.component.html file <app-address-card></app-address-card> Now in address-card.component.html <div> <h1>NU</hi> <h3>Computer</h3> <p>NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705</p> <div> <p>Phone:</p> <p>123-456-7890</p> <p>345-789-1234</p> </div> </div> Now we con't want it to be hard coded we want it dynamic So in address-card.component.ts we'll create a user object import { Component, Onlnit } from ‘@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user={ name:'NU', title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, phone: 123-456-7890", 345-789-1234" |
  • 6. } constructor() { } ngOnInit(): void { } } Now this user object needs to be in constructor import { Component, Onlnit } from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; constructor() { this.user={ name:NU’, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, phone:| 123-456-7890", "345-789-1234" | } } ngOnInit(): void { } } Now in address-card.component.html file <div> <h1>{{user.name}}</h1> <h3>{{user.title}}</h3> <p>{{user.address}}</p> <div> <p>Phone:</p> <p>{{user.phone[0]}}</p> <p>{{user.phone[1]}}</p> </div> </div> Now we want to loop through phone values <div>
  • 7. <h1>{{user.name}}</h1> <h3>{{user.title}}</h3> <p>{{user.address}}</p> <div> <p>Phone:</p> <p *ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> Now add another phone number in address-card.component.ts file and check ngFor is a directive. A directive is something that you add to an element. nglf What if there is no phone number import { Component, Onlnit } from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; constructor() { this.user={ name:NU’, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, } } ngOnInit(): void { } } But Phone: still appears Now we con't want to display when there are no phone numbers <div> <h1>{{user.name}}</h1> <h3>{{user.title}}</h3> <p>{{user.address}}</p> <div *nglf="user.phone.length>0"> <p>Phone:</p> <p *ngFor="let phNum of user.phone">{{phNum}}</p> </div>
  • 8. </div> nglf is not hiding the div element, it is removing it from the dom, if the expression evaluates to false This will also work <div *nglf="user.phone.length"> Also check by adding phone numbers import { Component, Onlnit} from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; constructor() { this.user={ name:NU’, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, phone:| 123-456-7890", "345-789-1234" | } } ngOnInit(): void { } } Passing input to component We want to pass the data <app-address-card name="NIIT University"></app-address-card> and in address-card.component.ts (Move the code from constructor to ngOnInit()) import { Component, Input, Onlnit } from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; @Input(‘name') userName: string | undefined; constructor() {
  • 9. } ngOnlnit(): void { this.user={ name:this.userName, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, ngOninit - executes code when component is fully initialized. A lifecycle hook that is called after Angular has initialized all data-bound properties of a directive. https://v2.angular.io/docs/ts/latest/guide/lifecycle-hooks.html https ://angular.io/guide/lifecycle-hooks When you use a selector angular creates an instance of a class. So the constructor is executed constructor - you can write code when object is created. (e.g. to populate data) Angular also does few other things after object is created (e.g. @Input). So after creating object it populates the values. It is after the creation of object that angular populates the value. You want to run the code once object has been fully created and initialized. You cannot run that code in the constructor. Angular provides Life cycle hooks for it. When angular object is fully initialized it will call ngOnInit method(). So you can write your @Input code in ngOnInit method. You can write the code without “implements Onlnit". It is only for compile checking for developer. The code would run the same. Angular is not looking for the interface, it is looking for the method (e.g. ngOnInit()) Passing member variables to components Apart from name passing we can pass other attributes of Address. That would be tedious. Instead we can pass an object which will contain all the values that the address-card component need. In order to create that object we need to create a class as an API for our component. In address-card folder create a new file user.model.ts export class User{ name: string designation: string address: string phone: string [] } The definite assignment assertion is a feature that allows a! to be placed after
  • 10. instance property and variable declarations to relay to TypeScript that a variable is indeed assigned for all intents and purposes, even if TypeScript’s analyses cannot detect so. Now in address-card.component.ts import { Component, Input, Onlnit} from '@angular/core’; import { User } from './user.model'; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; @Input(‘user') userOb}!: User; constructor() { } ngOnlnit(): void { this.user={ name:this.userObj.name, title:this. userObj.designation, address:this.userObj.address, phone:this.userObj.phone } In order to pass an instance of user - you need to first create that instance in app.component.ts file. App component is using address card component. App component need to pass instance of user to address-card component. In order to do that it need to create that instance first. Now in app.component.ts file (we'll make an instance of User) import { Component } from '@angular/core’; import { User } from './address-card/user.model'; @Component({ selector: 'app-root’, templateUrl: './app.component.htm’, styleUrls: ['./app.component.css'] }) export class AppComponent { user!: User; constructor(){
  • 11. this.user=new User() this.user.name="NU" this.user.designation="Computer" this. user.address="Neemrana" this.user.phone=[ '123-456-7890' ] } Now in app.component.html <app-address-card user="user"></app-address-card> will give error (because user is being assigned a string value - user) To evaluate the user <app-address-card [user]="user"></app-address-card> This telles angular not to take the value inline , instead evaluate it and take the member variable that it refers to. Styling angular components address-card.component.css .address-card{ border: 1px gray solid; padding: 15px; } -name{ font-family: "verdana", sans-serif; } .title{ font-style: italic; } .address{ font-size: 15x; } .phone{ border-left: 1px gray solid; padding-left: 5px; } Now | want class name, title etc only if the class happen in address-card class element (<div class="address-card">). So if there is another class title in html and you don't want it to be style like italic. You want only want "title" which is inside address-card to be style with italic. And in address-card.component.html <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1>
  • 12. <h3 class="title">{{user.title}}</n3> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p *ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> Now in app.component.html add a line <p class="title">Sample text</p> But it doesn't turn italic. Because the style that we apply in our address-card.component.css applies only to the markup inside the component. Now move this line <p class="title">Sample text</p> in address-card-component.html. Now it would work. This works because the way angular manages styling. Check in browser console.(An additional style has been appended to it). The [property] selector is used in CSS to style elements that have that particular property. This is angular trying to insulate styling that you are applying only to that component. It is intentional. Now how to apply global style?. You have global styles.css file (in src folder) Handling click event Expand and Collapse button for address Open address-card.component.ts file isCollapsed:boolean =true; Now in address-card.component.html file (address and phone should be in a div - because we want expand/collapse for both of them together) <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</n3> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> </div> <p class="title">Sample text</p> Now add a button in html (Expand/Collapse) <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</n3> <button>Expand / Collapse</button> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p>
  • 13. </div> </div> </div> <p class="title">Sample text</p> Define a function in address-card.component.ts file toggleCollapse(){ this.isCollapsed=!this.isCollapsed; } Now to call that function we will not use browser click event handler like <button onclick="abc()">. We want to call API of angular. So in address-card.component.html file <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</h3> <button (click)="toggleCollapse()">Expand / Collapse</button> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> </div> <p class="title">Sample text</p> Now to show right text - Expand or Collapse <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</h3> <button *nglf="isCollapsed" (click)="toggleCollapse()">Expand</button> <button *nglf="!isCollapsed" (click)="toggleCollapse()">Collapse</button> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> </div> <p class="title">Sample text</p> Two way data binding with ngModel (it can be used with forms) You update the component and view gets updated and vice versa. Open app.component.html file <input type="text'/> In app.component.ts file add instance variable inputText: string="Manish"
  • 14. And in app.component.html file <input type="text" value="inputText"/> In order to angular evaluate it put it in [] <input type="text" [value]="inputText"/> Now to map it In app.component.html file <app-address-card [user]="user"></app-address-card> <input type="text" [value]="inputT ext"/><br> {{inputText}} Check it. Right now it is not showing the change. Because right now there is only one way data binding. To use two way data binding use ngModel directive In app.component.html file <app-address-card [user]="user"></app-address-card> <input type="text" ngModel="inputText"/><br> {{inputText}} In order to use ngModel we need to make one more change - module. To use ngModel you need to import standard angular module in app.module.ts In app.module.ts (in NgModule section->imports) imports: [ BrowserMocule, AppRoutingModule, FormsModule 1, and the right import for FormsModule import { FormsModule } from '@angular/forms'; In app.component.html file (use [] with ngModel) <app-address-card [user]="user"></app-address-card> <input type="text" [ngModel]="inputText"/><br> {{inputText}} But it still doesn't works (because right now it is one way binding) To make it two way use [()] <app-address-card [user]="user"></app-address-card> <input type="text" [(ngModel)]="inputText"/><br><br> {{inputText}} The [()] syntax is referred to as banana-in-a-box. It helps to remember the order: brackets outside, parenthesis inside. 0 -> data flowing from the component to the view ()-> data from view to component (Compare click event made above) Creating and using multiple Create a new project third-project ng new third-project
  • 15. and delete the content of app.component.html file Open app.module.ts A module is a thing that consolidates different components. It does a lot more than that. Think of a module as some kind of container, some kind of namspace tha contains different things (e.g. AppComponent). So AppComponent is a part of AppModule. You can create multiple modules ina project and each module is going to contain components within it. So AppModule is a container for AppComponent. So modules might be required for big applications. To create a module ng generate module view It has created a folder view in app folder and a class in it And it does not have any declarations (there are no components associated with it now) It just have one import - CommonModule Now to create a component inside this module ng generate component view-component //don't run it But by default angular cli will create this component in app.module.ts (because that's where the root is (we are executing this command from the root - will assume that this component in app module)) But we want to create this component in view module So prefix with module name ng generate component view/view-component Notice it update view.module.ts file In declarations of view.module.ts file ViewComponentComponent has been added. We can also co all these things manually (without angular cli- by createing respective files and folders) Now ViewComponent is part of View Module (and it is nota part of app module) Open view-component.component.ts file and look at the selector. Now use this selector (in app module) app.component.html. It fails to compile. In browser inspector it will show app-view-component not known. To make it work in app.module.ts import ViewModule But it still doesn't works Because view.module.ts is working with a component that it is not exporting it. So in view.module.ts import { NgModule } from '@angular/core’; import { CommonModule } from '@angular/common'; import { ViewComponentComponent } from " view-component/view-component.component’; @NgModcule({ declarations: [ ViewComponentComponent 1 imports: [ CommonModule ], exports: [
  • 16. ViewComponentComponent ] }) export class ViewModule { } So all in all 1. The module that need it, needs to import the module, whatever module the component is declared in 2. Whatever module the component is declared in has to export the component Create a service If you want to create business functionality which doesn't have a view - you can create services. Services are like classes as components are. ng generate service test It will create a service in app location Open test.service.ts file @Injectable annotation tells angular that this class is a service. (@Component - Angular Component) (@NgModule - Angular module) (@Injectable - Angular service) Its reference is not added in app.module.ts file Now if you want test.service.ts to be part of app module then you need to declare in @NgModule. Services that you use in your modules need to be listed in providers section of your @NgModule providers:| TestService | In test.service.ts file import { Injectable } from '@angular/core’; @Injectable({ providedIn: 'root' }) export class TestService { printToConsole(arg: any){ console.log(arg) } constructor() { } } Now to call this method printToConsole we'll use Dependency Injection Dependency Injection We want to call printfoConsole method from AppComponent class First - let us call the method by using instance constructor(){ let svc=new TestService() svc.printtoConsole("Manish") } But in this scenario we are binding TestService with AppComponent class
  • 17. Second way - Dependeny Injection The idea of dependency injection is that when yo have a class that is dependent on another class - you don't have that class create that instance. What you do instead have the class declare its dependency and have that dependency injected. All you need to do declare a dependency on other services is just to create constructor arguments. Angular is going to look at the constructor and its arguments and it is going to see if any of these arguments are @Injectable. If there are services - angular is going to find that service (otherwise it will create one) and then it is going to pass that into the constructor (when this component is being created) In app.component.ts file import { Component } from '@angular/core’; import { TestService } from './test.service'; @Component({ selector: 'app-root’, templateUrl: './app.component.html’, styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(svc: TestService){ svc.printtoConsole("Manish") } title = 'third-project’; } Check it in browser console. Now it is available till the constructor runs. We can store it in instance variable. A shortcut for doing it. import { Component } from '‘@angular/core’; import { TestService } from './test.service'; @Component({ selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { private svc:TestService constructor(svc: TestService){ this.svc=svc; svc.printTtoConsole("Manish") } title = 'third-project’; } Or a shortcut import { Component } from '@angular/core’; import { TestService } from './test.service'; @Component({
  • 18. selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { ‘private svc:TestService constructor(private svc: TestService){ //this.svc=svc; this.svc.printToConsole("Manish") } title = 'third-project’; } Service Injection Context Difference between the components operate and the services operate in the context of module. A component can be declared inside module, in which case the component is only available to other components in the module. If you want to make it available outside the module you need to mark it in export; you need to add component in the exports and then other module needs it has to import. Ifa component has to be used outside its module - 2 rules 1. Owning module needs to export it 2. Then the module thats trying to use it needs to import the module. But in case of services it works differently. In app.module.ts - TestService has been provided in App module. You have added it in the providers section in the module. Now you can cdo dependency injection inside app.component.ts. Now there is another component - view component in the same project. Now what happens if we use dependency injection in view-component.component.ts and get access to TestService import { Component, Onlnit} from '@angular/core’; import { TestService } from ‘src/app/test.service'; @Component({ selector: 'app-view-component, templateUrl: './view-component.component.html’, styleUrls: ['.view-component.component.css'] }) export class ViewComponentComponent implements Onlnit { constructor(private svc: TestService) { svc.printtoConsole("From view module") } ngOnInit(): void { } } Now view.module.ts is not dependent on App module. It is other way round. The App module imports the view module. So can the view component access the service
  • 19. that is inside App component? We have seen it works. How is it possible? It is possible because of the way services works in Angular. Services are not restricted to the module that they are provided in. App module has TestService in providers. In the case of a component (e.g.AppComponent) that component is only available in the module. But i case of service (or providers) Angular creates a common shared space for services. There is a common area that contains all the services in your application that anybody cann add too. Let's suppos you have 3 different modules (each having different providers). Those providers are not restricted to that module. They become part of this common shared service space and any other component that makes a dependency injection which declares its dependency on any of the services is going to get the instance of that service. It doesn't have to be part of the module. The shared service space is referred as Injection context (Dependency Injection context). This list is available to all the components in your application. This is the reason why when Angular CLI created service it did not automatically added to any of the module. It did not Know where to provide TestService. REST with HttpClient How co you make REST API call with Angular? There is a service called HttpClient. In order to use that service import the module that the service comes with. The module contains service and the providers section. So when you import that module that service get added in injection context so that it is available to all your components. In app.module.ts import { NgModule } from '@angular/core’; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http’; import { AppRoutingModule } from './app-routing. module’; import { AppComponent } from './app.component; import { TestService } from '/test.service'; import { ViewModule } from '/view/view.module’; @NgModcule({ declarations: [ AppComponent 1 imports: [ BrowserModule, HttpClientModule, AppRoutingModule, ViewModule 1, providers: [TestService], bootstrap: [AppComponent] }) export class AppModule { }
  • 20. Now in app.component.ts (we'll inject service HttpClient) ngOnInit(}{ //let response =this. http.get(‘https://api.github.com/users/koushikkothagal’) //Can't do since you get an async object and in Angular world it is called Observable (earlier in Angular JS it was called promise) } In app.component.ts import { HttpClient } from '‘@angular/common/http’; import { Component } from '@angular/core’; import { TestService } from './test.service'; @Component({ selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { ‘private svc:TestService constructor(private svc: TestService, private http:HttpClient){ //this.svc=svc; this.svc.printToConsole("Manish") } ngOniInit(){ //let response =this. http.get(‘https://api.github.com/users/koushikkothagal’) //Can't do since it is an async request let obs=this.http.get(‘https://api.github.com/users/koushikkothagal’) obs.subscribe(()=>console.log("Got the response")) } title = 'third-project’; } Check in browser Change it to obs.subscribe((response)=>console.log(response))
  • 21. Installation NodeJS VS Code Angular CLI (https://angular.io/cli) npm install -g @angular/cli (@abc/xyz is called "scoped" package name. These names are of the format @group/package) ng version ng new first-project Is cd first-project Is Open project in VS Code To run the project ng serve On browser http://localhost:4200/ Check index.html file app-root component is available in app folder app.component.ts, app.component.html and app.component.css files provide functionality and look and feel of app component A component is a combination of view and backing logic app.component.ts provides backing logic, app.component.html and app.component.css files providelook and feel of app component Make a change in index.html and check in browser Make a change in app.component.ts title = 'My first-project'’; Dynamic logic will come from type script file Make a change in app.component.css h1{ color: red; } app.component.spec.ts is for test case Delete all the content in app.component.html and save Creating your first component In terminal stop the server (Ctrl C) Create a new component ng generate component hello-world Check in VS Code Check hello-world.component.ts You have a selector for it which is going to instantiate this component. You can use the selector in html markup of a component and then it is going to call it as a child component Open app.component.html file Run the server ng serve We have created a component and use it in another component You can use hello-world component multiple times and it is going to create those many instances
  • 22. Check in browser Anatomy of a component We want to make a date component which prints current date Open terminal in VS Code ng generate component date Open date-component.ts and see the selector In app.component.html <app-date></app-date> Check it Every angular component is mainly a typescript class. Think of the HTML and CSS as just extra "attachments" to the main typescript file. So angular CLI creates a class for a component. Or in order to create a component you have to create a typescript class (if you were to do it yourself). After you have created the class you need to register the class as an angular componert. It is done with @Component annotation. You can try changing selector template Url attributes and also do required changes and can try it out(In date.component.ts file ) Binding data from component class Create a member variable in DateComponent class message: string = "hello"; In date.component.html file {{message}} Check it in browser Now instead of "hello" text change it to new Date() message: string = new Date().toDateString(); (or toString) In date.component.html file <div> <p>The date is:</p> <p> {{message}} </p> </div> Data binding in Angular refers to binding the data in the component instance to the HTML template. Any change to the data get automatically updated in the view. Right now it is one way flow of data - from component to html Data binding and async We want to constantly update time export class DateComponent implements Onlnit { dateMessage: string; constructor() { let currentDate=new Date() this.dateMessage=currentDate.toDateString()+' '+currentDate.toLocaleTimeString() } ngOnInit(): void { } }
  • 23. And in html file <div> <p>The date is:</p> <p> {{dateMessage}} </p> </div> Right now the new Date object is created in constructor. So, it currently only executes when the page is loaded which causes the component instance to be created. In oorder to update time we need to create new Date object every second. So we'll use setlnterval in constructor export class DateComponent implements Onlnit { dateMessage: string | undefined; constructor() { setinterval(() => { let currentDate = new Date() this.dateMessage = currentDate.toDateString() + '' + currentDate.toLocaleTimeString() }, 1000) } ngOnInit(): void { } } Check in browser Template Interpolation Text interpolation lets you incorporate dynamic string values into your HTML templates.Interpolation refers to embedding expressions into marked up text. By default, interpolation uses the double curly braces {{ and }} as delimiters. {{dateMessage}}-double curly brackets trigger angular to do string interpolation In html {{1+1}} Define a num variable in class {{num*2}} Now double curly brackets with function call import { Component, Onlnit } from ‘@angular/core’; @Component({ selector: 'app-date’, templateUrl: './date.component.htm’, styleUrls: ['./date.component.css'] }) export class DateComponent implements Onlnit { dateMessage: string | undefined; num: number=1 2; constructor() { setinterval(() => { let currentDate = new Date()
  • 24. this.dateMessage = currentDate.toDateString() + '' + currentDate.toLocaleTimeString() }, 1000) } ngOnlnit(): void { add(a:number,b:number}{ return a+b } } And in html file <div> <p>The date is:</p> <p> {{dateMessage}} </p> {{num*2}}<br> {{add(num,2)}} </div> Check it this is required in class but not in html import { Component, Onlnit } from '@angular/core’; @Component({ selector: 'app-date’, templateUrl: './date.component.htm’, styleUrls: ['./date.component.css'] }) export class DateComponent implements Onlnit { dateMessage: string | undefined; num: number=1 2; constructor() { setinterval(() => { let currentDate = new Date() this.dateMessage = currentDate.toDateString() + '' + currentDate.toLocaleTimeString() }, 1000) } ngOnlnit(): void { add(a:number,b:number}{
  • 25. return a+b } someMeth() //here this.add(this.num,2) } } Looping with ngFor Make a new seconc-project Clear code from app.component.htm| and delete line title = 'app'; in app.component.ts Check with ng serve Stop the server and create new component address card ng generate component address-card It get registered in app.module.ts To check address-card component works, from address-card.component.ts file take the selector and use it in app.component.html file <app-address-card></app-address-card> Now in address-card.component.html <div> <h1>NU</hi> <h3>Computer</h3> <p>NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705</p> <div> <p>Phone:</p> <p>123-456-7890</p> <p>345-789-1234</p> </div> </div> Now we con't want it to be hard coded we want it dynamic So in address-card.component.ts we'll create a user object import { Component, Onlnit } from ‘@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user={ name:'NU', title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, phone: 123-456-7890", 345-789-1234" |
  • 26. } constructor() { } ngOnInit(): void { } } Now this user object needs to be in constructor import { Component, Onlnit } from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; constructor() { this.user={ name:NU’, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, phone:| 123-456-7890", "345-789-1234" | } } ngOnInit(): void { } } Now in address-card.component.html file <div> <h1>{{user.name}}</h1> <h3>{{user.title}}</h3> <p>{{user.address}}</p> <div> <p>Phone:</p> <p>{{user.phone[0]}}</p> <p>{{user.phone[1]}}</p> </div> </div> Now we want to loop through phone values <div>
  • 27. <h1>{{user.name}}</h1> <h3>{{user.title}}</h3> <p>{{user.address}}</p> <div> <p>Phone:</p> <p *ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> Now add another phone number in address-card.component.ts file and check ngFor is a directive. A directive is something that you add to an element. nglf What if there is no phone number import { Component, Onlnit } from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; constructor() { this.user={ name:NU’, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, } } ngOnInit(): void { } } But Phone: still appears Now we con't want to display when there are no phone numbers <div> <h1>{{user.name}}</h1> <h3>{{user.title}}</h3> <p>{{user.address}}</p> <div *nglf="user.phone.length>0"> <p>Phone:</p> <p *ngFor="let phNum of user.phone">{{phNum}}</p> </div>
  • 28. </div> nglf is not hiding the div element, it is removing it from the dom, if the expression evaluates to false This will also work <div *nglf="user.phone.length"> Also check by adding phone numbers import { Component, Onlnit} from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; constructor() { this.user={ name:NU’, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, phone:| 123-456-7890", "345-789-1234" | } } ngOnInit(): void { } } Passing input to component We want to pass the data <app-address-card name="NIIT University"></app-address-card> and in address-card.component.ts (Move the code from constructor to ngOnInit()) import { Component, Input, Onlnit } from '@angular/core’; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; @Input(‘name') userName: string | undefined; constructor() {
  • 29. } ngOnlnit(): void { this.user={ name:this.userName, title:‘Computer’, address:'NH 8, Delhi - Jaipur Expy, Neemrana, Rajasthan 301705’, ngOninit - executes code when component is fully initialized. A lifecycle hook that is called after Angular has initialized all data-bound properties of a directive. https://v2.angular.io/docs/ts/latest/guide/lifecycle-hooks.html https ://angular.io/guide/lifecycle-hooks When you use a selector angular creates an instance of a class. So the constructor is executed constructor - you can write code when object is created. (e.g. to populate data) Angular also does few other things after object is created (e.g. @Input). So after creating object it populates the values. It is after the creation of object that angular populates the value. You want to run the code once object has been fully created and initialized. You cannot run that code in the constructor. Angular provides Life cycle hooks for it. When angular object is fully initialized it will call ngOnInit method(). So you can write your @Input code in ngOnInit method. You can write the code without “implements Onlnit". It is only for compile checking for developer. The code would run the same. Angular is not looking for the interface, it is looking for the method (e.g. ngOnInit()) Passing member variables to components Apart from name passing we can pass other attributes of Address. That would be tedious. Instead we can pass an object which will contain all the values that the address-card component need. In order to create that object we need to create a class as an API for our component. In address-card folder create a new file user.model.ts export class User{ name: string designation: string address: string phone: string [] } The definite assignment assertion is a feature that allows a! to be placed after
  • 30. instance property and variable declarations to relay to TypeScript that a variable is indeed assigned for all intents and purposes, even if TypeScript’s analyses cannot detect so. Now in address-card.component.ts import { Component, Input, Onlnit} from '@angular/core’; import { User } from './user.model'; @Component({ selector: 'app-address-card’, templateUrl: './address-card.component.htm'’, styleUrls: ['./address-card.component.css'] }) export class AddressCardComponent implements Onlnit { user: any; @Input(‘user') userOb}!: User; constructor() { } ngOnlnit(): void { this.user={ name:this.userObj.name, title:this. userObj.designation, address:this.userObj.address, phone:this.userObj.phone } In order to pass an instance of user - you need to first create that instance in app.component.ts file. App component is using address card component. App component need to pass instance of user to address-card component. In order to do that it need to create that instance first. Now in app.component.ts file (we'll make an instance of User) import { Component } from '@angular/core’; import { User } from './address-card/user.model'; @Component({ selector: 'app-root’, templateUrl: './app.component.htm’, styleUrls: ['./app.component.css'] }) export class AppComponent { user!: User; constructor(){
  • 31. this.user=new User() this.user.name="NU" this.user.designation="Computer" this. user.address="Neemrana" this.user.phone=[ '123-456-7890' ] } Now in app.component.html <app-address-card user="user"></app-address-card> will give error (because user is being assigned a string value - user) To evaluate the user <app-address-card [user]="user"></app-address-card> This tells angular not to take the value inline , instead evaluate it and take the member variable that it refers to. Styling angular components address-card.component.css .address-card{ border: 1px gray solid; padding: 15px; } -name{ font-family: "verdana", sans-serif; } .title{ font-style: italic; } .address{ font-size: 15x; } .phone{ border-left: 1px gray solid; padding-left: 5px; } Now | want class name, title etc only if the class happen in address-card class element (<div class="address-card">). So if there is another class title in html and you don't want it to be style like italic. You want only want "title" which is inside address-card to be style with italic. And in address-card.component.html <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1>
  • 32. <h3 class="title">{{user.title}}</n3> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p *ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> Now in app.component.html add a line <p class="title">Sample text</p> But it doesn't turn italic. Because the style that we apply in our address-card.component.css applies only to the markup inside the component. Now move this line <p class="title">Sample text</p> in address-card-component.html. Now it would work. This works because the way angular manages styling. Check in browser console.(An additional style has been appended to it). The [property] selector is used in CSS to style elements that have that particular property. This is angular trying to insulate styling that you are applying only to that component. It is intentional. Now how to apply global style?. You have global styles.css file (in src folder) Handling click event Expand and Collapse button for address Open address-card.component.ts file isCollapsed:boolean =true; Now in address-card.component.html file (address and phone should be in a div - because we want expand/collapse for both of them together) <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</n3> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> </div> <p class="title">Sample text</p> Now add a button in html (Expand/Collapse) <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</n3> <button>Expand / Collapse</button> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p>
  • 33. </div> </div> </div> <p class="title">Sample text</p> Define a function in address-card.component.ts file toggleCollapse(){ this.isCollapsed=!this.isCollapsed; } Now to call that function we will not use browser click event handler like <button onclick="abc()">. We want to call API of angular. So in address-card.component.html file <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</h3> <button (click)="toggleCollapse()">Expand / Collapse</button> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> </div> <p class="title">Sample text</p> Now to show right text - Expand or Collapse <div class="address-card"> <h1 class="name">{f{fuser.name}}</h1> <h3 class="title">{{user.title}}</h3> <button *nglf="isCollapsed" (click)="toggleCollapse()">Expand</button> <button *nglf="!isCollapsed" (click)="toggleCollapse()">Collapse</button> <div *nglf="tisCollapsed"> <p class="address">{{user.address}}</p> <div class="phone" *nglf="user.phone.length"> <p>Phone:</p> <p “ngFor="let phNum of user.phone">{{phNum}}</p> </div> </div> </div> <p class="title">Sample text</p> Two way data binding with ngModel (it can be used with forms) You update the component and view gets updated and vice versa. Open app.component.html file <input type="text'/> In app.component.ts file add instance variable inputText: string="Manish"
  • 34. And in app.component.html file <input type="text" value="inputText"/> In order to angular evaluate it put it in [] <input type="text" [value]="inputText"/> Now to map it In app.component.html file <app-address-card [user]="user"></app-address-card> <input type="text" [value]="inputT ext"/><br> {{inputText}} Check it. Right now it is not showing the change. Because right now there is only one way data binding. To use two way data binding use ngModel directive In app.component.html file <app-address-card [user]="user"></app-address-card> <input type="text" ngModel="inputText"/><br> {{inputText}} In order to use ngModel we need to make one more change - module. To use ngModel you need to import standard angular module in app.module.ts In app.module.ts (in NgModule section->imports) imports: [ BrowserMocule, AppRoutingModule, FormsModule 1, and the right import for FormsModule import { FormsModule } from '@angular/forms'; In app.component.html file (use [] with ngModel) <app-address-card [user]="user"></app-address-card> <input type="text" [ngModel]="inputText"/><br> {{inputText}} But it still doesn't works (because right now it is one way binding) To make it two way use [()] <app-address-card [user]="user"></app-address-card> <input type="text" [(ngModel)]="inputText"/><br><br> {{inputText}} The [()] syntax is referred to as banana-in-a-box. It helps to remember the order: brackets outside, parenthesis inside. 0 -> data flowing from the component to the view ()-> data from view to component (Compare click event made above) Creating and using multiple modules Create a new project third-project ng new third-project
  • 35. and delete the content of app.component.html file Open app.module.ts A module is a thing that consolidates different components. It does a lot more than that. Think of a module as some kind of container, some kind of namspace tha contains different things (e.g. AppComponent). So AppComponent is a part of AppModule. You can create multiple modules ina project and each module is going to contain components within it. So AppModule is a container for AppComponent. So modules might be required for big applications. To create a module ng generate module view It has created a folder view in app folder and a class in it And it does not have any declarations (there are no components associated with it now) It just have one import - CommonModule Now to create a component inside this module ng generate component view-component //don't run it But by default angular cli will create this component in app.module.ts (because that's where the root is (we are executing this command from the root - will assume that this component in app module)) But we want to create this component in view module So prefix with module name ng generate component view/view-component Notice it update view.module.ts file In declarations of view.module.ts file ViewComponentComponent has been added. We can also co all these things manually (without angular cli- by createing respective files and folders) Now ViewComponent is part of View Module (and it is nota part of app module) Open view-component.component.ts file and look at the selector. Now use this selector (in app module) app.component.html. It fails to compile. In browser inspector it will show app-view-component not known. To make it work in app.module.ts import ViewModule But it still doesn't works Because view.module.ts is working with a component that it is not exporting it. So in view.module.ts import { NgModule } from '@angular/core’; import { CommonModule } from '@angular/common'; import { ViewComponentComponent } from " view-component/view-component.component’; @NgModcule({ declarations: [ ViewComponentComponent 1 imports: [ CommonModule ], exports: [
  • 36. ViewComponentComponent ] }) export class ViewModule { } So all in all 1. The module that need it, needs to import the module, whatever module the component is declared in 2. Whatever module the component is declared in has to export the component Create a service If you want to create business functionality which doesn't have a view - you can create services. Services are like classes as components are. ng generate service test It will create a service in app location Open test.service.ts file @Injectable annotation tells angular that this class is a service. (@Component - Angular Component) (@NgModule - Angular module) (@Injectable - Angular service) Its reference is not added in app.module.ts file Now if you want test.service.ts to be part of app module then you need to declare in @NgModule. Services that you use in your modules need to be listed in providers section of your @NgModule providers:| TestService | In test.service.ts file import { Injectable } from '@angular/core’; @Injectable({ providedIn: 'root' }) export class TestService { printToConsole(arg: any){ console.log(arg) } constructor() { } } Now to call this method printToConsole we'll use Dependency Injection Dependency Injection We want to call printfoConsole method from AppComponent class First - let us call the method by using instance constructor(){ let svc=new TestService() svc.printtoConsole("Manish") } But in this scenario we are binding TestService with AppComponent class
  • 37. Second way - Dependeny Injection The idea of dependency injection is that when you have a class that is dependent on another class - you don't have that class create that instance. What you do instead have the class declare its dependency and have that dependency injected. All you need to do declare a dependency on other services is just to create constructor arguments. Angular is going to look at the constructor and its arguments and it is going to see if any of these arguments are @Injectable. If there are services - angular is going to find that service (otherwise it will create one) and then it is going to pass that into the constructor (when this component is being created) In app.component.ts file import { Component } from '@angular/core’; import { TestService } from './test.service'; @Component({ selector: 'app-root’, templateUrl: './app.component.html’, styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(svc: TestService){ svc.printtoConsole("Manish") } title = 'third-project’; } Check it in browser console. Now it is available till the constructor runs. We can store it in instance variable. A shortcut for doing it. import { Component } from '‘@angular/core’; import { TestService } from './test.service'; @Component({ selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { private svc:TestService constructor(svc: TestService){ this.svc=svc; svc.printTtoConsole("Manish") } title = 'third-project’; } Or a shortcut import { Component } from '@angular/core’; import { TestService } from './test.service'; @Component({
  • 38. selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { ‘private svc:TestService constructor(private svc: TestService){ //this.svc=svc; this.svc.printToConsole("Manish") } title = 'third-project’; } Service Injection Context Difference between the components operate and the services operate in the context of module. A component can be declared inside module, in which case the component is only available to other components in the module. If you want to make it available outside the module you need to mark it in export; you need to add component in the exports and then other module needs it has to import. Ifa component has to be used outside its module - 2 rules 1. Owning module needs to export it 2. Then the module thats trying to use it needs to import the module. But in case of services it works differently. In app.module.ts - TestService has been provided in App module. You have added it in the providers section in the module. Now you can cdo dependency injection inside app.component.ts. Now there is another component - view component in the same project. Now what happens if we use dependency injection in view-component.component.ts and get access to TestService import { Component, Onlnit} from '@angular/core’; import { TestService } from ‘src/app/test.service'; @Component({ selector: 'app-view-component, templateUrl: './view-component.component.html’, styleUrls: ['.view-component.component.css'] }) export class ViewComponentComponent implements Onlnit { constructor(private svc: TestService) { svc.printtoConsole("From view module") } ngOnInit(): void { } } Now view.module.ts is not dependent on App module. It is other way round. The App module imports the view module. So can the view component access the service
  • 39. that is inside App component? We have seen it works. How is it possible? It is possible because of the way services works in Angular. Services are not restricted to the module that they are provided in. App module has TestService in providers. In the case of a component (e.g.AppComponent) that component is only available in the module. But i case of service (or providers) Angular creates a common shared space for services. There is a common area that contains all the services in your application that anybody cann add too. Let's suppos you have 3 different modules (each having different providers). Those providers are not restricted to that module. They become part of this common shared service space and any other component that makes a dependency injection which declares its dependency on any of the services is going to get the instance of that service. It doesn't have to be part of the module. The shared service space is referred as Injection context (Dependency Injection context). This list is available to all the components in your application. This is the reason why when Angular CLI created service it did not automatically added to any of the module. It did not Know where to provide TestService. REST with HttpClient How co you make REST API call with Angular? There is a service called HttpClient. In order to use that service import the module that the service comes with. The module contains service and the providers section. So when you import that module that service get added in injection context so that it is available to all your components. In app.module.ts import { NgModule } from '@angular/core’; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http’; import { AppRoutingModule } from './app-routing. module’; import { AppComponent } from './app.component; import { TestService } from '/test.service'; import { ViewModule } from '/view/view.module’; @NgModcule({ declarations: [ AppComponent 1 imports: [ BrowserModule, HttpClientModule, AppRoutingModule, ViewModule 1, providers: [TestService], bootstrap: [AppComponent] }) export class AppModule { }
  • 40. Now in app.component.ts (we'll inject service HttpClient) ngOnInit(}{ //let response =this. http.get(‘https://api.github.com/users/koushikkothagal’) //Can't do since you get an async object and in Angular world it is called Observable (earlier in Angular JS it was called promise) } In app.component.ts import { HttpClient } from '‘@angular/common/http’; import { Component } from '@angular/core’; import { TestService } from './test.service'; @Component({ selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { ‘private svc:TestService constructor(private svc: TestService, private http:HttpClient){ //this.svc=svc; this.svc.printToConsole("Manish") } ngOniInit(){ //let response =this. http.get(‘https://api.github.com/users/koushikkothagal’) //Can't do since it is an async request let obs=this.http.get(‘https://api.github.com/users/koushikkothagal’) obs.subscribe(()=>console.log("Got the response")) } title = 'third-project’; } Check in browser Change it to obs.subscribe((response)=>console.log(response)) Github API access with username in form Update the view component In view-component.component.html file User Name : <input type="text"><br> <button>Search</button> We need to bind the input to member variable and then bind search click to a function
  • 41. So User Name : <input type="text" [(ngModel)]="UserName"><br> <button>Search</button> For this to work we need FormModule in our View Module. So in view.module.ts file import { NgModule } from '@angular/core’; import { CommonModule } from '@angular/common'; import { ViewComponentComponent } from " view-component/view-component.component’; import { FormsModule } from '@angular/forms'; @NgModcule({ declarations: [ ViewComponentComponent 1, imports: [ CommonModule, FormsModule ], exports:[ViewComponentComponent] }) export class ViewModule { } Again in view-component.component.html file User Name : <input type="text" [(ngModel)]="UserName"><br> <button (click)="search()">Search</button> Now in view-component.component.ts file import { HttpClient } from '@angular/common/http'; import { Component, Onlnit } from ‘@angular/core’; import { TestService } from ‘src/app/test.service'; @Component({ selector: 'app-view-component, templateUrl: './view-component.component.html’, styleUrls: ['.view-component.component.css'] }) export class ViewComponentComponent implements Onlnit { userName: string="" response: any; constructor(private http: HttpClient) { search(){ let obs=this.http.get(‘https://api.github.com/users/'+this.userName) obs.subscribe((response)=>this.response=response) console.log(this.response) }
  • 42. ngOnlnit(): void { } } Remove Git API code from app.component.ts file Check it in browser console Now we want to print the result in browser In view-component.component.html file User Name : <input type="text" [(ngModel)]="UserName"><br> <button (click)="search()">Search</button> <br><br> {{response. login} Check it (Ignore the errors in the browser console (it is because when the component loads up initially it has a blank response (because userName is blanl))) Again in view-component.component.html file User Name : <input type="text" [(ngModel)]="UserName"><br> <button (click)="search()">Search</button> <br><br> <p>Login Name : {{response.login}}</p> <p>Number of repos : {{response.public_repos}}</p> <p>Number of gists : {{response.public_gists}}</p> <p>Number of followers : {{response.followers}}</p> Check it Now we don't want Login Name :,Number of repos,etc to be displayed (click refresh) when there is no name. So use nglf User Name : <input type="text" [(ngModel)]="UserName"><br> <button (click)="search()">Search</button> <br><br> <div *nglf="response"> <p>Login Name : {{response.login}}</p> <p>Number of repos : {{response.public_repos}}</p> <p>Number of gists : {{response.public_gists}}</p> <p>Number of followers : {{response.followers}}</p> </div> Check it. Now errors in browser console has gone. Otherway to do it (apart from nglf (use 7?)) User Name : <input type="text" [(ngModel)]="UserName"><br> <button (click)="search()">Search</button> <br><br>
  • 43. <p>Login Name: {{response?.login}}</p> <p>Number of repos : {{response?.public_repos}}</p> <p>Number of gists : {{response?.public_gists}}</p> <p>Number of followers : {{response?.followers}}</p> But in this case text is appearing. So use nglf Building an Angular Application Using ng serve we get a simple dev server. And it is very handy. You make a change in codebase, it automatically updates it and it automatically refreshes your browser By default we get hot reload in Angular. But when you'll be hosting this application, you con't need it. This is a waste. Secondly, when you create Angular application you are having a lot of code that could be optimized (when you are hosting on server). When you run ng serve command - Angular looks at your codebase and bundles up all your module and it creates a local server. Now this is a development server. Now how does it matter. Open your browser inpector and come to Network tab and refresh the page again. There are bunch of JS files that are loading. (runtime.js, styles.js, vendor.js). These are all pretty big files. And they are not even minified. We need to minify these files. If we want a simple component (three files) without any server side code, this is something you can host and deploy on CDN and have the user loaded without needing a server running at all times. This is static content. To generate this static content of the project - ng build ng build runs the Angular CLI which looks at your project and generates HTML, CSS and JS into one folder and that is going to be independent of Angular CLI, Node version. It is just static asset that you can deploy A dist folder is created. And it again has a bunch of files in it that can be hosted. You can deploy this folder into CDN To do it install nom package npm install http-server -g http-server lets you to host a directory on your machine as if you are hosting it ona CDN. You can access it locally. To run it http-server <dir name> http-server dist/third-project It is by default ng build --configuration production It also creates hashes (e.g. main.#value). The reason being if you update a file and build it again a new hash would be generated. So you cache your values on the server. Knowing that when there is a new build you'll get a new file name (that's referred to by index.html}. As long as you are not caching index.html it is going to fetch these new file names. So you get latest build while leveraging caching. Check it on browser http://127.0.0.1 :8081/ and it runs without ng serve So we are now running it without Angular. Check browser inspector. The message which was appearing earlier (Angular is running in development mode.) has gone. Check the Network Tab also and click runtime.js and the file is minified.
  • 44. Project with routing ng new fourth-project Open in VS Code Check in package.json - you have a dependency on router Check in app.module.ts AppRoutingModule has been included And you have a file app-routing.module.ts - Open it. It has a class AppRoutingModule. It has some constant called routes (which is an empty array (which is fo type Routes). Routes is basically an array of Route class (position mouse array on Routes) It is for configuring your routes. And then you pass this configuration in @NgModcule({ imports: [RouterModule.forRoot(routes)], Now we want to create 2 routes. Let us first create 2 components home and settings ng g c home ng gc settings In your app.module.ts file both of them are imported In app-routing.module.ts file import { NgModule } from '@angular/core’; import{ RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './nome/home.component'’; import { SettingsComponent } from './settings/settings.component; const routes: Routes = [ {path:'home' component:domeComponent}, {path:'settings' ,component:SettingsComponeni}, 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } Now in order to provide a window for angular to put component in the view - Go in your app.component.html file and delete all lines except <router-outlet></router-outlet> This is required by Angular to know where to put the components Check in browser localhost:4200/home localhost:4200/settings Route Redirects and Wildcard Setup a default route - so that when user is not entering the URL It should automatically redirect to home We want to make home as the default route and we also want to handle errors (if
  • 45. somebody enters wrong URL) One way is (in app-routing.module.ts file) import { NgModule } from '@angular/core’; import{ RouterModule, Routes } from '@angular/router’; import { HomeComponent } from './home/home.component'; import { SettingsComponent } from '/settings/settings.component’; const routes: Routes = [ {path: ", component:HomeComponent}, {path:'home' component:domeComponent}, {path:'settings' ,component:SettingsComponeni}, 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } Check in browser So you can have multiple paths mapped to same component. But we would like to do it with a redirect. import import import import NgModule } from '@angular/core’; RouterModule, Routes } from '@angular/router’; HomeComponent } from './nome/home.component'’; SettingsComponent } from './settings/settings.component; “aa const routes: Routes = [ {path: ", redirectTo:'/home',pathMatch:'full’}, {path:'home' component:domeComponent}, {path:'settings' ,component:SettingsComponeni}, 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } Check it. This can also be used {path: ", redirectTo:'/home',pathMatch:'prefix’}, Now for error handling. Specifying a component when a path doesn't exists. e.g. localhost:4200/manish It doesn't shows anything. Check error in browser inspector.
  • 46. We want to show error message by component when someone tries to access a URL which doesn't exists. Use wildcard ng g c page-not-found import { NgModule } from '@angular/core’; import{ RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'’; import { PageNotFoundComponent } from " /page-not-found/page-not-found.component'’; import { SettingsComponent } from './settings/settings.component’; const routes: Routes = [ {path: ", redirectTo:'/home',pathMatch:'full’}, {path:'home' component:domeComponent}, {path:'settings' ,component:SettingsComponeni}, {path: '**' component:PageNotFoundComponent} 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } Check it Configuring Child routes You want a route resolution inside a route. We want to configure settings/profile and settings/contact and this we want to do within settings component. So profile and contact needed to be rendered in a small window within settings. In settings.component.html file <h1>Settings Page</h1> Check localhost:4200/settings Now we want component to be rendered below this Settings Page header when we enter settings/profile or settings/contact. ng g c settings-profile ng g c settings-contact We want it to match to a sub component or sub route or child route. Now in app-routing.module.ts file can we add path like {path:'settings/profile',component:SettingsComponent}, Doing this will not give angular a clue that it is child route. So to do it we need to add another property in settings url - children and its datatype is again Route array. (Route array has aproperty called children and the value of that is another Route array. You can specify an array of Route as children to an existing Route. That's how you have child Route) In app-routing.module.ts file
  • 47. import { NgModule } from '@angular/core’; import{ RouterModule, Routes } from '@angular/router’; import { HomeComponent } from './nome/home.component'’; import { PageNotFoundComponent } from " /page-not-found/page-not-found.component'’; import { SettingsContactComponent } from " /settings-contact/settings-contact.component'; import { SettingsProfileComponent } from ./settings-profile/settings-profile.component’; import { SettingsComponent } from './settings/settings.component; const routes: Routes = [ {path: ", redirectTo:'/home',pathMatch:'full’}, {path:'home' component:domeComponent}, path:'settings’, component:SettingsComponent, children: [ {path:'profile’,component:SettingsProfileComponent}, {path:'contact',component:SettingsContactComponent}, ] }, {path: '**' component:PageNotFoundComponent} 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } Now the point is where Angular is going to put this rendered component? You have one router-outlet at application level (app.component.html). This is where Settings component went. Now where the child is going to go in Settings component. For it you have to create a router-outlet in Settings component as well. So in settings.component.html file <h1>Settings Page</h1> <router-outlet></router-outlet> This is where child of Settings component will get plugged in. Check it with settings/profile and settings/contact Now we want setting url default to profile import { NgModule } from '@angular/core’; import{ RouterModule, Routes } from '@angular/router’; import { HomeComponent } from './nome/home.component'’; import { PageNotFoundComponent } from " /page-not-found/page-not-found.component'’;
  • 48. import { SettingsContactComponent } from " /settings-contact/settings-contact.component'; import { SettingsProfileComponent } from ./settings-profile/settings-profile.component’; import { SettingsComponent } from '/settings/settings.component’; const routes: Routes = [ {path: ", redirectTo:'/home',pathMatch:'full’}, {path:'home' component:domeComponent}, path:'settings’, component:SettingsComponent, children: [ {path: ", redirectTo:'profile’,pathMatch:"full’}, {path:'profile’,component:SettingsProfileComponent}, {path:'contact',component:SettingsContactComponent}, ] }, {path: '**' component:PageNotFoundComponent} 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } Again one more (for settings/not found) import { NgModule } from '@angular/core’; import{ RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'’; import { PageNotFoundComponent } from " /page-not-found/page-not-found.component'’; import { SettingsContactComponent } from " /settings-contact/settings-contact.component'; import { SettingsProfileComponent } from ./settings-profile/settings-profile.component’; import { SettingsComponent } from '/settings/settings.component’; const routes: Routes = [ {path: ", redirectTo:'/home',pathMatch:'full’}, {path:'home' component:domeComponent}, path:'settings’, component:SettingsComponent, children: [ {path: ", redirectTo:'profile’,pathMatch:"full’},
  • 49. {path:'profile’,component:SettingsProfileComponent}, {path:'contact',component:SettingsContactComponent}, {path: '**' redirectTo:'profile’, pathMatch:'full'} | }, {path: '**' component:PageNotFoundComponent} 1; @NgModcule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } For a wrong settings URL it will redirect it to profile page. Showing Navigation for routes In app.component.html Check in browser Now the problem is when you click these link it is doing full page refresh. Also check it by going into browser inspector - network tab. This is not we want. We ware building SPA. The whole page is loading because when you do <a href=...It is actually instruction for the browser to load the URL. But you don't want the browser to load the full page URL. Now how to tell angular to change the route. It can be done using routerLink directive. <h1>My App</h1> <a routerLink="home">Home</a> <a routerLink="settings">Settings</a> <router-outlet></router-outlet> Now it works. It doesn't do a full page refresh. Now same thing with class property resolution. In app.component.ts file import { Component } from '@angular/core’; @Component({ selector: 'app-root’, templateUrl: './app.component.html’, styleUrls: ['./app.component.css'] }) export class AppComponent { homeRoute="home" settingsRoute="settings" title = 'fourth-project'’; }
  • 50. And In app.component.html <h1>My App</h1> <a [routerLink]="homeRoute">Home</a> <a [routerLink]="settingsRoute">Settings</a> <router-outlet></router-outlet> Another good way for it In app.component.ts file import { Component } from '@angular/core’; @Component({ selector: 'app-root’, templateUrl: './app.component.htm', styleUrls: ['./app.component.css'] }) export class AppComponent { homeRoute="home" routes=[ {linkName: ‘Home’ url:'‘home’}}, {linkName: 'Settings',url:'settings'}, ] } And In app.component.html <h1>My App</h1> <a *ngFor="let route of routes" [routerLink]="route.url">{{route.linkKName}}</a> <router-outlet></router-outlet> Check it Now to add sub nav In settings.component.html file <h1>Settings Page</h1> <a *ngFor="let route of routes" [routerLink]="route.url">{{route.linkKName}}</a> <router-outlet></router-outlet> And in settings.component.ts file import { Component, Onlnit} from '@angular/core’; @Component({ selector: 'app-settings’, templateUrl: './settings.component.htm'’, styleUrls: ['./settings.component.css'] }) export class SettingsComponent implements Onlnit { routes=[ {linkName: 'Profile’,url:'profile’}, {linkName: ‘Contact Info',url:‘contact'’},
  • 51. ] constructor() { } ngOnInit(): void { } } Check it
  • 52. Angular Technologies @ Angular @ JavaScript / TypeScript @ Angular CLI @ Reactive programming, RxJS, Observables, operators @ Jasmine, Karma @ Redux, ngRx
  • 54. Show current date and time
  • 55. HTML Add a div and paragraph Add button JS Code to get date/time Get the paragraph DOM element Update value Code function to handle button click
  • 64. Root component pe Ne, header main footer /oN summary details sidebar foN nav updates
  • 65. HTML Add a div and paragraph Add button JS Code to get date/time Get the paragraph DOM element Update value Code function to handle button click
  • 70. Compute the current date date.component.html — DateComponent Class Show the computed date
  • 71. export class DateComponent implements OnInit { J constructor() { } neOnInit() { } | }
  • 85. One component per view Component 1 Component 2 Component 3
  • 86. One root component per view Component 1 Component 2 Component 3
  • 87. One root component per view Component 1 Component 2 Component 3
  • 90. Views URL Component View 1 foo.com/view1 View 2 foo.com/view2
  • 92. Routing in Angular @ Define your route URLs @ Create Angular components for each view (one for each route) @ Configure Angular to map route URLs to components
  • 93. https://nodejs.org/en/ Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. NVM installation link https://github.com/nvm-sh/nvm For mac curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash Copy the commands from above command export NVM_DIR="$HOME/.nvm" [ -s "BNVM_DIR/nvm.sh" ] && . "BNVM_DIR/nvm.sh" # This loads nvm [ -s "BNVM_DIR/bash_completion" ] && . "BNVM_DIR/bash_completion" # This loads nvm bash_completion and put it in ~/.bash_profile Close the terminal and open new terminal nvm -v If it doesn't runs source ~/.bash_profile Now come to Usage section of https://github.com/nvm-sh/nvm and run nvm install node If you install older version like nvm install 6.14.4 then node switches automatically to that version. Check it by node -v NVM for windows download https://github.com/coreybutler/nvm-windows REPL - Read Evaluate Print Loop node Node prompt lets you write JS code and execute it 243 vara a=10 a a*3 var b=a*4 b For multiline commands if(a>10){ console.log("Greater than 10") } To exit ctrl+c - ctrl+c or ctrl+d or .exit After exiting memory gets cleared vi one.js
  • 94. console.log("Hello World"); node one var a=10; var b=20; var c=a+b; console.log(c}; Editor VSCode Module - Every JS file is a module in itself. Make a addjs file function add(a,b) return a+b; console.log(add(1,2)); Make another file first.js require('./add.js'); function greet(name){ console.log("Hello "+name); } greet("Manish"); require - is the way to import a module Move require('./add.js'); at the end of file and run again Now what if we want to call the add function in first.js require('./add.js'); function greet(name){ console.log("Hello "+name); } greet("Manish"); add(3,4); node first - will give an error - add is not defined Node modules are encapsulated by default. So once require("./add.js") finishes - add function is not available. How do we do it? In add.js function add(a,b) { } return a+b;
  • 95. console.log(add(1 ,2)); module.exports=add; and in first.js var addFn= requie('./add.js’); function greet(name){ console.log("Hello "+name); } greet("Manish"); console.log(addFn(3,4)):; What if you have more functions to be exported? In add.js function add(a,b) { } function subtract(a,b) { return a+b; return a-b; } console.log(add(1 ,2)); module.exports={ add: add, subtract: subtract }; O //module.exports={ // add, // subtract I}; //So this time we are exporting object So in first.js var operObj= requie('./add.js'); function greet(name){ console.log("Hello "+name); } greet("Manish"); console.log(operObj.add(3,4)); Another way to export is In add.js function add(a,b) { } function subtract(a,b) { } return a+b; return a-b;
  • 96. console.log(add(1 ,2)); module.exports.add=add; module.exports.subtract=subtract; Run it and check again There is a shortcut code - instead of module.exports.add=add; write exports.add=add; (Actually nodejs is running var exports=module.exports; So exports is available as an alias) Another code for add.js exports.add=(a,b)=>a+b; // Arrow function and in first.js var {add}= requie('./add.js'); //Using Destructuring function greet(name){ console.log("Hello "+name); } greet("Manish"); console.log(add(3,4)); Require with node api nodejs.org/api/index.htm! Search for read Click on the Reacline on left Copy the line const reacdLine=require(‘readLine’) Create a new file greet.js Copy the usage sample const readLine=require(‘readLine’) const readline = require(‘readline’); const rl = readline.createlnterface({ input: process.stdin, output: process.stdout }); rl.question(‘What do you think of Node.js? ', (answer) => { /! TODO: Log the answer in a database console.log( Thank you for your valuable feedback: ${answer})); rl.close(); }); Change it to const readline = require(‘readline’); const rl = readline.createlnterface({ input: process.stdin, output: process.stdout
  • 97. }); rl.question(‘What is your name? ', (name)=>{ console.log( Hello {$name} ); rl.close(); }); WAP to add 2 numbers Writing user input to a file nodejs.org/api/index.html - there is a FilSystem link Click on fs.writeFile and check the documentation Make a file greet-to-file.js const fs=require(‘fs'); fs.writeFile(‘greeting.txt’,'Hello World',err=>{ console.log('Error occured’); }); Check it. Actually you should check const fs=require(‘fs'); fs.writeFile(‘greeting.txt','Hello World’ ,err=>{ ifferr) { console.log('Error occured’); } }); Another one with arguments const fs=require(‘fs'); const writeGreetingToFile=(name)=>{ fs.writeFile(‘greeting. txt’, Hello ${name} ,err=>{ if(err) { console.log('Error occured’); } ys } writeGreeting ToFile('Manish’); Take input from user and store it in a file const fs=require(‘fs'); const readline = require(‘readline’); const writeGreetingToFile=(name)=>{ fs.writeFile(‘greeting. txt’, Hello ${name} ,err=>{ if(err) { console.log('Error occured’);
  • 98. const rl = readline.createlnterface({ input: process.stdin, output: process.stdout }); rl.question(‘What is your name? ', (name)=>{ /Iconsole.log( Hello {$name} ); rl.close(); writeGreeting ToFile(name); }); Making a project npm -v mkdir timezone cd timezone npm init Is Make index.js file console.log(‘Hello World’); To run node index Or (a common command) In package.json "scripts" add "start" :"node index.js", Now run it with npm start npm test You can create your own script like "myscript":"Is" You run it with npm myscript — //It will fail npm run myscript We'll use moments - a tz utility Open momenitjs.com npm install moment (it will download in your current folder) In index.js file let moment=require(‘moment'’) console.log(moment().format('ddda’) Run using npm start Now we con't want to share the downloaded libraries with others. We share the project code. (Delete node_modules folder). The other person will run npm install Creating a command line utility npm init
  • 99. npm install moment npm install moment-timezone Make an index.js file const moment=require(‘moment); moment.tz.setDefault(‘America/Los_Angeles'); const targetTimezone="Europe/Paris"; console.log(moment().tz(targetTimezone).format()); /iconsole.log(-The time at the ${targetTimezone} is ${moment().tz(targetTimezone).format()} ); Now we want to do it from command line arguments node index.js "Asia/Kolkata" But it doesn't take the arguments The way to get to command line arguments is using an object called process.argv which is available to Node const moment=require(‘moment); moment.tz.setDefault(‘America/Los_Angeles'); const targetTimezone="Europe/Paris"; console.log(process.argv); console.log(-The time at the ${targetTimezone} is ${moment().tz(targetTimezone).format()} ); node index.js "Asia/Kolkata" const moment=require(‘moment); moment.tz.setDefault(‘America/Los_Angeles'); let targetTimezone; if(process.argv.length!=3)}{ console.log("Usage : node <script> <tz>"); } else { } //const targetTimezone="Europe/Paris"; //console.log(process.argv); console.log(The time at the ${targetTimezone} is ${moment().tz(targetTimezone).format()} ); targetTimezone=process.argv[2]; node index.js "Asia/Kolkata" Callbacks in Node.js Make a file file-api-.js let fs=require(‘fs’); //fs.writeFileSync(‘test.txt',,A sample text’); //console.log(‘After file is written’); fs.writeFile(‘test.txt’,"Text written async’ (err)=>{ console.log(‘After file is writtem’); }) console.log(‘This should print after previous line’);
  • 100. node file-api.js Take 2 nos. from user and print their sum Take 3 nos. from user and find out the greatest number Basic function abc(}{} console.log(abc()); var fn=function (){ console.log("Sample output"); } fn(); setTimeout(fn,5000); function placeAnOrder(orderNumber) { console.log("Customer Order : ",orderNumber); cookAndDeliverFood(function(){ console.log("Delivered Food Order : ",orderNumber); }); } function cookAndDeliverFood(callback){ setTimeout(callback,5000); } placeAnOrder(1) placeAnOrder(2) placeAnOrder(3); placeAnOrder(4):; (5) (6) (7) placeAnOrder placeAnOrder placeAnOrder Reference to an Object var amit={ favFood: "DalChaval", favMovie: "3 Idiots" } var person=amit; person.favFood="Dosa"; console.log(amit.favFood); this reference var person={
  • 101. printFirstName: function(){ console.log("Amit’); console.log(this===person); } } person.printFirstName(); //The default calling context is global function sam(){ console.log("Naveen"); console.log(this===global); } sam(); Prototype function User(){ this.name=""" this.life=100; this.giveLife=function (targetPlayer){ targetPlayer.life+=1; console.log(this.name +" give 1 life to "+targetPlayer.name); } } var amit=new User(); var naveen=new User‘(); amit.name="Amit"; naveen.name="Naveen"; amit.giveLife(naveen); console.log("Amit : "+amit.life); console.log("Naveen : "+naveen life); //Add function to all objects User.prototype .uppercut=function(targetPlayer){ targetPlayer.life-=3; console.log(this.name +" gave uppercut to "+targetPlayer.name); } naveen.uppercut(amit); console.log("Amit : "+amit.life); console.log("Naveen : "+naveen life); //Add properties to all objects User.prototype.magic=50; console.log("Amit : "+amit.magic); console.log("Naveen : "+naveen.magic); Shared state of modules (Default behaviour of NodeJS - Any time you export an Object from a module that object gets shared among every other modules)
  • 102. Make movies.js module.exports={ favMovies: "" } Make naveen.js var movies=require("./movies"); movies.favMovie="3 Idiots"; console.log("Amit's favourite movie is : "+movies.favMovie); Make amit.js var movies=require("./movies"); console.log("Amit's favourite movie is : "+movies.favMovie); Make app.js require("./naveen.js"); require("./amit.js"); Object Factory (Default behaviour of NodeJS - Any time you export an Object from a module that object gets shared among every other modules. So anytime we want to create a new object we actually need to export a function that creates a new Object. This is what Object factory is - It is an Object which creates another Object) In movie.js module.exports=function(}{ return { favMovie: } } Now ian naveen.js var movies=require("./movies"); var naveenMovies=movies(); naveenMovies.favMovie="3 Idiots"; console.log("Naveen's favourite movie is : "+naveenMovies.favMovie); Now in amit.js var movies=require("./movies"); var amitMovies=movies(); console.log("Amit's favourite movie is : "+amitMovies.favMovie); Core Modules var fs=require('fs'); fs.writeFileSync(“abc.txt","A sample text")| console.log(fs.readFileSync("abc.txt").toString); var path=require("path"); var abc="DesktopDataabc.txt"; console.log(path.normalize(abc);
  • 103. console.log(path.dirname(abc); console.log(path.baseame(abc}); console.log(path.extname(abc); setinterval(function(){ console.log("Hello"); },200); console.log(__ dirname); console.log(__ pathname); Basic Server Make server.js var http = require(‘http’); function onRequest(request, response) { console.log("A user made a request " + request.url); response.writeHead(200, { "Content-Type": "text/plain" }); response.write("Hi user"); response.end(); } http.createServer(onRequest).listen(8888); console.log("Server is running..."); Simple Web File Server Make index.html file <h1>My Page</h1> In server.js var http = require(‘http’); var fs=require('fs'); function send404Response(response){ response.writeHead(200, { "Content-Type": "text/plain" }); response.write("Error 404:Page not found"); response.end(); } function onRequest(request, response) { if(request.method=="GET" && request.url=="/"}{ response. .writeHead(200, { "Content-Type": "text/html" }); fs.createReadStream("./index.html").pipe(response); jelse{ send404Response(response); } } http.createServer(onRequest).listen(8888); console.log("Server is running..."); Connect (Server Framework)(With this middleware you can stack the function calls)
  • 104. npm install connect In server.js var connect = require(‘connect'’); var http = require(‘http’); var app=connect()}; http.createServer(app).listen(8888); console.log("Server is running..."); Now var connect = require(‘connect'’); var http = require(‘http’); var app=connect()}; function doFirst(request,response,next){ console.log("Hello"); } app.use(doFirst) http.createServer(app).listen(8888); console.log("Server is running..."); With this middleware you can stack the function calls var connect = require(‘connect'’); var http = require(‘http’); var app=connect()}; function doFirst(request,response,next){ console.log("Hello"); next(); } function doSecond(request,response,next){ console.log("Bye"); next(); } app.use(doFirst) app.use(doSecond) http.createServer(app) listen(8888); console.log("Server is running..."); Remark next(} and check var connect = require(‘connect'’); var http = require(‘http’); var app=connect()}; function doFirst(request,response,next){ console.log("Hello"); //next(); function doSecond(request,response,next){ console.log("Bye"); next(); app.use(doFirst) app.use(doSecond)
  • 105. http.createServer(app).listen(8888); console.log("Server is running..."); var connect = require(‘connect'’); var http = require(‘http’); var app=connect()}; function profile(request,response){ console.log("User profile"); } function forum(request,response){ console.log("User forum"); } app.use("/profile" profile); app.use("/forum",forum); http.createServer(app).listen(8888); console.log("Server is running..."); Template PUG index.pug file html head title= title body hi= message (Also show the difference of title = title) index.js file var express = require(‘express'); var app = express(); app.set('view engine',‘pug') app.get(‘/’, function(req, res){ res.render(‘index', { title: "My Page", message:"A sample message" }); }); app.listen(3000); Show the generated page in Inspector If you want to add doctype Then do it with title= abc
  • 106. It will dissapear Again do it with title= "abc" Then p Asample paragraph Show the difference with p= A sample paragraph (Will give an error) p = "A sample paragraph" Then a(href="https://nucleus.niituniversity.in/") NU Website Now show the anchor tag within p tag (by indenting) Then ul li Dosa li Idli li Parantha Then put this ul tag in div tag For form input element input(name="fname", type="text", id="fn") With placeholder input(name="fname", type="text", id="fn" placeholder="First Name") Then adding a label to it label(for="fn") Enter Name Show input for password Now table table tr td label First Name td input(name="fn" id="fn") tr td label Last Name td input(name="In",id="In") Now form tag form(method="post" action="get") label(for="{n") Enter Name &nbsp; input(name="fname", type="text", id="fn") input(type="submit",value="Save")
  • 107. Now CSS In public folder make css folder and main.css file h1{ color: red; } In head tag link(rel="stylesheet" href="/static/css/main.css") And in index.js file app.use(/static',express.static(‘public’)) Now make js/main.js in public folder alert("Hello"); And in index.pug In head script(src="/static/js/main.js") Now extends layout Make layout.pug in views folder Cut the contents of index.pug and paste it in layout.pug Now cut the form part of it and write block content (in line with html tag) in layout.pug file Now in index.js file extends layout block content var ‘express' //var bodyParser = require(‘body-parser); //var multer = require(multer); //var upload = multerQ; var ‘/', function ‘form’ ‘view engine’, 'pug' //app.set(‘views’, './views'); // for parsing application/json
  • 108. //fapp.use(express.jsonQ); // for parsing application/xwww- //form-urlencoded // for parsing multipart/form-data //fapp.use(upload.array(); //app.use(express.static(‘public’)); app ‘/', function(req, res console req.body res "recieved your request!" app var express = require(‘express’); var bodyParser = require(‘body-parser’); /var multer = require(multer’); /var upload = multer(); var app = express(); app.get(’/', function(req, res){ res.render(‘form’); }); app.set('view engine’, 'pug’); /lapp.set(‘views’, './views'); // for parsing application/json //app.use(bodyParser.json()); //app.use(express.json()); // for parsing application/xwww- //app.use(bodyParser.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true })); //form-urlencoded // for parsing multipart/form-data //app.use(upload.array()}; app.use(express.static(‘public’));
  • 109. app.post('/', function(req, res){ console.log(req.body); res.send("recieved your request!"); }); app.listen(3000): The Components object is deprecated. It will soon be removed. - Due to Selenium addon Don't use : while printing variable content "start": "nodemon -e js,pug", app.use(bodyParser()); //Now deprecated You now need to call the methods separately app.use(bodyParser.urlencoded()}; app.use(bodyParser.json()); Cookies var ‘express' var app app ‘/', function(reg, res res ‘name’, ‘Manish’, {maxAge: ‘cookie set’): //Sets name = express //res.cookie(rememberme’, '1', { expires: new Date(Date.nowQ + 900000), httpOnly: true }); app To send multiple cookies var ‘express' var app app ‘/', function(reg, res res ‘name’, ‘Manish’, {maxAge: res ‘mob' maxAge: res ‘cookie set’); //Sets name = express
  • 110. app.listen(3000 Retrieving cookies var express = require(express' var app = express var cookieParser = require(‘cookie-parser’): //is required in retrieving cookies app.use(cookieParser //app.use(express.urlencoded({extended: true})) app.get(/', function(req, res res.cookie(‘name’, ‘Manish’ res.cookie(‘mob', 9015 res.send(‘cookie set’); //Sets name = express app.get(/cook', function(reg, res console.log(‘Cookies: ', reg.cookies res.send(‘cookie in console’): //Sets name = express app.listen(3000 Session A session secret in connect is simply used to compute the hash. Without the string, access to the session would essentially be "denied". var express = require(express' var cookieParser = require(‘cookie-parser’ var session = require(‘express-session' var app = express app.use(cookieParser app.use(session secret: "MySecret" resave: true saveUninitialized: true app.get(/', function(req, res
  • 111. "You visited this page " "times" else "Welcome to this page for the first time!" mongod --dbpath ../data/db curl -X PUT --data "name=Toy#20storyéyear=1995érating=8.5" http://localhost:3000/movies/101 User authentication npm init -y npm i express berypt npm i --save-dev nodemon Make server,js file In package.json file in scripts section “devStart": "nodemon server.js", On terminal In server.js const express=require('express’) const app=express() app. listen(3000) This server doesn't do anything npm run devStart Add const users=[] app.get('/users',(req,res)=>{ res.json(users) }) Install REST Client in VS Code (to make REST calls) Make another file request.rest GET http://localhost:3000/users and click on Send Request Now check by adding in users array users=[{name: 'Manish’}]
  • 112. Now app.post('/users',(req,res)=>{ const user={name: req.body.name,password: req.body.password} users.push(user) res.status(201).send() }) Now to use json app.use(express.json()) This will allow application to allow JSON In request.rest file POST hittp://localhost:3000/users Content-Type: application/json { "name": "Manish", "password": "Abc" } Now the password is visible And to make it hash hash(salt+'password') hash(salt2+'passworc’') We want password to be hashed so even if someone gets access to db.... Now in server.|s const berypt=require(‘bcrypt') Now change app.post app.post('/users' async (req,res)=>{ try{ const salt=await bcrypt.genSalt() const hashedPassword=await bcrypt.hash(req.body.password, salt) console.log(salt) console.log(hashedPassword) const user={name: req.body.name,password: hashedPassword} users.push(user) res.status(201).send() } catch{ res.status(500).send() } }) See the salt and hashedPassword on server console Now to reduce the code app.post('/users' async (req,res)=>{ try{ //const salt=await bcrypt.genSalt() const hashedPassword=await bcrypt.hash(req.body.password,10) //salt replaced y 10 (def value)
  • 113. //console.log(salt) //console.log(hashedPassword) const user={name: req.body.name,password: hashedPassword} users.push(user) res.status(201).send() catch{ res.status(500).send() } }) Now to login In request.rest file copy paste POST request and POST hitp://localhost:3000/users/login Content-Type: application/json { "name": "Manish", "password": "Abc" } Now create the route in server.js file app.post('/users/login' async (req,res)=>{ const user=users.find(user=>user.name=req.body.name) if(user==null) return res.status(400).send("Cannot find user") try{ if(await bcrypt.compare(req.body.password,user.password)){ res.send("success") } else{ res.send("Unauthorized") } }catch{ res.status(500).send() } }) Now from request.rest file create the user using first post request And then try login with different password JWT npm init -y npm i express jsonwebtoken dotenv dotenv file which is going to contain our secret tokens for JWT Make .env file npm i --save-dev nodemon Make server,js file In package.json file in scripts section “devStart": "nodemon serverjs",
  • 114. On terminal npm run devStart In server.js const express=require(‘express') const app=express() app. listen(3000) This server doesn't do anything Now const posts=[ { username: ‘Manish’, title: ‘one’ }, { username: ‘Amit’, title: 'two' } ] app.get('/posts',(req,res)=>{ res.json(posts) }) Install REST Client in VS Code (to make REST calls) Make another file requests.rest GET hittp://localhost:3000/posts and click on Send Request Now we need to authenticate our request using JWT so that we don't let everyone access the posts - only specific users, so app.posi(‘/login' (req,res)=>{ //Authenticate User }) To do authentication we want to use jsonwebtoken And to do that we need to require the library const jwt=require(‘jsonwebtoken') app.use(express.json()) app.posi(‘/login' (req,res)=>{ //Authenticate User const username=req.body.username const user={name: username} const access Token=jwt.sign(user,process.env.ACCESS TOKEN_SECRET) res.json({access Token: access Token}) }) Now in terminal open node prompt node >require(‘crypto').randomBytes(64).toString(‘hex’)
  • 115. and again >require(‘crypto').randomBytes(64).toString(‘hex') Copy the generated tokens in env file ACCESS _TOKEN_SECRET=45102a2f8c44e202cdcc0648cdfb68ca6dc54879eca95 0e5fa431981e55a8b8491 dabe1 3313ef781 92c33bbd29a3ddc1 6688675f1f7a7851e5 e793ea7991ae88 REFRESH_TOKEN_SECRET=a2892c578591 2c42a509f8d43f231075a36201 aeb067 716d709ecb23ec04e7fccd47906e1 bceb26fc984b2b50ebe4eb6261 8346d264a9b70f e786635788dede5 Now in requests. rest file HHH POST hitp://localhost:3000/login Content-Type: application/json { } It will show an error -s Because we are not loading .env variables into our process.env To do it add this line on top of server.js file require(‘dotenv’).config() "username": "Manish" Now again send the POST request This returns access token (which has no expiration date and user info saved in it). So we can access any of our endpoints with the user info. Now let's create a middleware which is going to authenticate our token This token is going to come into header (authorization) function authenticate Token(req,res,next){ const authHeader=req.headers['authorization’] const token= authHeader && authHeader.split(’ ')[1] if (token==null) res.sendStatus(401) jwt.verify(token,process.env.ACCESS_TOKEN_SECRET ,(err,user)=>{ if(err) return res.sendStatus(403) req.user=user next() }) } Now change app.get(‘posts') app.get(‘/posts’, authenticate Token, (req,res)=>{ res.json(posts. filter(post=>post.username===req.user.name)) //It is only going to return the post which the user has access to }) In requests.rest file
  • 116. GET hittp://localhost:3000/posts Authorization: Bearer <token> Now test it Then login as Amit To use them across many different servers In package.json in start script “devStart2": "nodemon server2.js", Copy server.js into server2.js and inserver2.js change port to 4000 In another prompt npm run devStart2 Now inrequests.rest file make a post request form server at port 3000 and copy the key and use it in GET on server at port 4000 Now we can make authentication server different Rename server2.js to authServer.js In package.json file instead of "devStart2": "nodemon server2.js" “devStartAuth": "nodemon authServer.js" and npm run devStartAuth From server.js file remove login section (delete app.post(‘login’) In authServer you can delete const posts array and app.get(‘posts') method Right now token has no expiration date The idea of REFRESH Token is that you save the token in the same spot and then normal access token have short expiration date So if someone gets your access token he has got the access for few minutes before that access is revoked and then user must use REFRESH Token to get a new token And it also does have the same problem that your token gets stolen and someone else can use to refresh your token and that's where the idea of invalidating the REFRESH token is. You can essentially create logout route which deletes a REFRESH token So the reason for using REFRESH token is 1. So that user can invalidate 2. And to take all your authentication and authorization code and move it away from normal server https://www.youtube.com/watch?v=SnoAwLP 1a-0&list=PL4cUxeGkcC¥iqqESP8335 DA5cRFp8loyp
  • 117. In Node Application, any async function accepts a callback as the last parameter and a callback function accepts an error as the first parameter. Callback Function A callback function is a function (It can be any function Anonymous Function, Arrow Function) passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. function show() { console.log("I am show Function"); function geeky(callback) { callback(); } geeky(show)}; function show(a) { console.log("I am show Function" + a); } function geeky(callback) { var a = 101; callback(a); } geeky(show)}; let x= function (}{ console.log(“Called from inside a function”) } let y=function(callback){ console.log(“do something”); callback(); } y(x) let calc=function(num1 ,jnum2,calcType){ if (calcType==="add”) return num1+num2; } else if(calcType==="multiply”) { } return num1*num2;
  • 118. console.log(calc(2,3,’add’)); console.log(calc(2,3,’multiply’)); let add=function(a,b){ return a+b; } let multiply=function(a,b){ return a*b; let calc=function(num1 ,num2,callback}{ return callback(num1 ,num2); } console.log(calc(2,3,add)); Now try with multiply Now add let doWhatever=function(a,b){ console.log(’ Numbers are ${a} and ${b}>); } and then console.log(calc(2,3,doWhatever)): Now | don’t have to define function outside console.log(calc(2,3,function(a,b){return a-b;})) Now to check if the argument is function let calc=function(num1 ,num2,callback}{ if(typeof callback==="function”) return callback(num1 ,num2); } var myArr=[{ num: 5, str: “apple” }, { num: 7, str: “cabbage” }, { num: 1, str: ‘ban’ }; myArr.sort(function(val1 ,val2){ if(val1 .str>val2.str) return -1; else return 1; }); console.log(myArr);
  • 119. var fs=require("fs") var file="data.txt" fs.exists(file function (exists){ if(exists}{ fs.stat(file function(err,stat){ if(err) throw err; if(stat.isFile(}){ fs.readFile (file, "utf8" function(err,data){ if(err} throw err; console.log(data); Or var fs=require("fs") var file="data.txt" function readFile(err,data){ if (err) throw err; console.log(data); } function status(err,stat){ if (err) throw err; if(stat.isFile(}){ fs.readFile(file ,"utf8" read File); } } function fileExists(exists){ if(exists) fs.stat(file status); } fs.exists(file, fileExists); app.use(bodyParser.urlencoded({ extended: false })); If extended is false, you can not post "nested object" person[name] = 'cw' /! Nested Object = { person: { name: cw } }
  • 120. If extended is true, you can do whatever way that you like. When extended property is set to true, the URL-encoded data will be parsed with the qs library. On the contrary, when extended property is set to false, the URL-encoded data will instead be parsed with the querystring library. The differences between parsing with “qs library’ vs “querystring library” qs library allows you to create a nested object from your query string. var qs = require("qs") var result = qs.parse("person[name]=bobby&person[age]=3") console.log(result) //{ person: { name: ‘bobby’, age: '3' } } query-string library does not support creating a nested object from your query string. var queryString = require("query-string") var result = queryString.parse("person[name]=bobby&person[age]=3") console.log(result) //{ 'person[age]': '3', 'person[name]': 'bobby' } qs library will not filter out '?' from the query string. var qs = require("qs") var result = qs.parse("?a=b") console.log(result) //{ '?a': 'b'} query-string library will filter out '?' from the query string. var queryString = require("query-string") var result = queryString.parse("?a=b") console.log(result) //{ a: 'b'} Many of us that have been using the Node/Express Framework have been used to installing another piece of middleware in order for us to be able to read the “body” of an incoming JSON object. This piece of middleware was called body-parser and used to not be part of the Express framework. The good news is that as of Express version 4.16+, their own body-parser implementation is now included in the default Express package so there is no need for you to download another dependency. npm uninstall body-parser
  • 122. Continuous Integration = Continuous integration systems are avital part of any Agile team because they help enforce the ideals of Agile development = Jenkins, acontinuous build tool, enables teams to focus antheir work by automating the build, artifact management, and deployment processes = Jenkins’ core functionality and flexibility allow it to fit in avariety of environments and can help streamline the development process for all stakeholders involved
  • 123. CI Defined “Continuous Integration is asoftware development practice where members of ateam integrate their work frequently, usually each person integrates at least daily - leadingto multiple integrations per day. Eachintegration 1s verified by an automated build (including test) to detect integration errors asquickly as possible’— Martin Fowler ob Continuous Integration Code is pulled over every commit made in the source code BEE —— | Every change made in the source code is Commit changes to build continuously the source code en
  • 124. CI— What does ttreallymean? = At aregular frequency (ideally at every commit), the system 1s: = Integrated = All changes up until that point are combined into the project » Built = The code is compiled into an executable or package = Tested = Automated test suites are run Archived = Versioned and stored so it can be distributed asis, if desired Deployed = Loaded onto asystem where the developers can interact with it
  • 125. CI -Workflow tle Continuous Ie esstre ws Build System Executable/ Repository Package Artifact Testing Results Deployment Developers
  • 126. CI— Benefits = Immediate bug detection = Nointegration step in the lifecycle = Adeployable system at any given point = Record ofevolution ofthe project
  • 127. CI— Thetools = Code Repositories =» SVN, Mercurial, Git = Continuous Build Systems # Jenkins, Bamboo, Cruise Control = Test Frameworks = =JUnit,Cucumber, CppUnit = Artifact Repositories = Nexus,Arttfactory,Archiva
  • 128. Jenkins Jenkins is an open source automation tool written in Java with plugins built for Continuous Integration purpose. Jenkins is used to build and test your software projects continuously making it easier for developers to integrate changes to the project, and making it easier for users to obtain a fresh build. With Jenkins, organizations can accelerate the software development process through automation. Jenkins integrates development life-cycle processes of all kinds, including build, document, test, package, stage, deploy, static analysis and much more.
  • 129. Jenkins 2005 - Hudson wasfirst release by Kohsuke Kawaguchi dSun Microsystems 2010— Oracle bought Sun Microsystems Due to anaming dispute, Hudson was renamed to Jenkins = Oracle continued development of Hudson (as abranch of the original) Javabased Continuous Build System Runsin servlet container = ~~Glassfish, Tomcat Supported by over 400 plugins = SCM.Testing, Notifications, Reporting, Artifact Saving, Triggers, External Integration
  • 130. What can Jenkinsdo? = Generate test reports = Integrate with many different Version Control Systems = Pushto various artifact repositories = Deploys directly to production or test environments = Notify stakeholders of build status
  • 131. How Jenkins works Setup When setting up aproject in Jenkins, out of the box youheavethe following general options: = Associating with aversion control server = Triggering builds Polling, Periodic, Building based on other projects = Execution of shell scripts, bashscripts, Ant targets, and Maven targets = Artifact archival = Publish JUnit test results and Javadocs = Email notifications Asstated earlier, plugins expand the functionality even further
  • 132. a Jenkins Work Flow Clone Mount | / Run Pull build repository in Workspace as——+ container environment Workspace volume / image | Build | | Test | ! Po Workspace | Build artifacts | Test results | ; f — | Dispose container / 4
  • 133. Enhancing Jenkins = Jenkins plugin system can enable a wide range of features including (but certainly not limited to) » SCM = Mercurial, Git, Subversion " Testing = Selenium,Windmill,TestLink = Notifications # IRC,Twitter, Jabber = Reporting = Doxygen, PMD, Findbugs = Artifact Saving » Artifactory, Amazon $3, SCP » Triggers = Jabber, Directory Watchers = External Integration = GitHub, Bugzilla, JIRA = And most importantly — The CI Game = Apoints based game where developers compete against each other to develop the most stable, well- tested code
  • 134. Who uses Jenkins? Linked{ i). GAGEx) SAIL x Ween BOEING mozilla FOUNDATION
  • 135. Tying it into Agile For an Agile team, Jenkins provides everything needed for a robust continuous build system ‘Jenkins supports Agile principles by constantly providing access to working copies of software Jenkins’ extensibility allows the system to adapt to many different pre-existing environments
  • 136. Nu wN > Installation of Jenkins Download the latest stable Jenkins WAR file to an appropriate directory on your machine. Open up a terminal/command prompt window to the download directory. Run the command java -jar jenkins. war. Browse to http://localhost:8080 and wait until the Unlock Jenkins page appears. Continue on with the Post-installation setup wizard below. You can change the port by specifying the --httpPort option java -jar jenkins.war --httpPort=9090
  • 137. Jenkins GUI Configurations To use and configure Jenkins, visit the following address in your browser http://y our-ip-address: 8080 You will be surprised to see its welcome screen where you will be able to configure its different parameters for your system. € Jenkins Jenkins + ENABLE AUTO REFRESH e New Item fad description & Feope Welcome to Jenkins! Build History Please Create new jobs to get started. é Manage Jenkins A Credentials Build Queue a No builds in the queue. Build Executor Status = 1 Idle 2 Idle —
  • 138. Installation on Ubuntu Install Java Version 8 — Jenkins is a Java based application, hence Java is a must. sudo yum install java-1.8.0-openjdk Download Jenkins war File — This war is required to install Jenkins. weet http://updates.jenkins-ci.org/download/war/2.7.3/jenkins.war apt-get install Jenkins
  • 139. (~ ) THE BASICS OF SETTING UP A JENKINS MASTER SERVER Discover, Install and Manage Plugins Jenkins has hundreds of useful plugins. Plugins will eliminate the need to create custom scripting to solve common problems with minimal pain. 1.Navigate to Jenkins Web Interface > Login as Admin > Manage Jenkins > Manage Plugins > Available (Tab) Select checkbox for all the plugins you want to install Select "Download now and install after restart" at the bottom of the page. 2. After Jenkins finishes restarting, the installed plugins will appear under Manage Plugins > Installed (Tab) Here are a few Jenkins plugin recommendations: Git - allows you to integrate GitHub to clone repository GitHub Pull Request Builder - builds pull requests in GitHub and reports results Swarm - enables slaves to auto-discover nearby Jenkins master and join it automatically Sauce OnDemand - allows you to integrate Sauce Labs Selenium testing with Jenkins Pipeline - suite of plugins that lets you orchestrate automation, simple or complex Slack - allows posting of build notifications to a Slack channel Thinbackup - simply backs up the global and job-specific configurations Ne yy,
  • 140. a As an admin of Jenkins, the Configure System page is a critical configuration section. This page represents a variety of sections, each correlating to a different configuration area from generic Jenkins settings, defining global environment variables, and most installed plugins are configured on this page. Steps Navigate to Jenkins Web Interface > Login as Admin > Manage Jenkins > Configure System Configure the root directory for workspace and build record. Configure System Settings Home directory /opt/jenkins WIGIKEpAES Tatot DanSesory ${JENKINS_ HOME}workspace/${ITEM_FULLNAME} Build Record Root Directory ${ITEM_ROOTDIRYbuilds
  • 141. JDK JDK installations Ant Ant installations JDK Name OpenJDK Version 7 #) Install automatically @ Install from java.sun.com Version | Java SE Development Kit 7u79 r “| | agree to the Java SE Development Kit License Agreement © Installing JDK requires Oracle account. Please enter your username/ password Oe)em eae) se Bre) yim) Add Installer + Add JDK List of JDK installations on this system Ant Name Apache #) Install automatically @ Install from Apache Version| 1.9.6 ¥
  • 142. a Configure Global Settings Straight out of the box Jenkins will allow anyone to run anything as a user of Jenkins along with admin permissions, which is bad. I suggest enabling Lightweight Directory Access Protocol (LDAP), wich allows you to use corporate service. Users can log into Jenkins with their usual company login credentials. Navigate to Jenkins Web Interface > Login as Admin > Manage Jenkins > Configure Global Security Select checkbox to enable security. Set TCP port for JNLP slave agents to 9000. Select LDAP from the Access Control (Security Realm) section and enter your LDAP server address:
  • 143. (— Continue.. pees Contra Security Realm Delegate 10 serviet container Gitnub Authentication Plugin Jenkins’ own user database © Lorp Sener Waps /mycompany 5490 © Syntax of server field is SERVER or SERVER: PORT of idaps J/SERVER|:PORT] 1.Select matrix-based security from the Access Control (Authorization) section 2.Select the checkbox for Prevent Cross Site Request Forgery Exploits, and Enable Slave --> Master Access Control
  • 144. Create New Job Step 1 — Go to the Jenkins dashboard and Click on New Item 1 Dashboard Penkins] = =_ ae localhost: 2080), enkine Op) = & Jenkins a when Kins moan sarees ‘at New Hem acd dascipbon MB People Welcome to Jenkins! = Build History yo Manage Jenkine | Fisss= create mew pobes to get started. a. Credeniiale: Baa uae Rio builds in the queue Gull Executor Sia iue. 1 kile 2 kobe Pegs gececmted: Set 10 SNE TA RET AP) eb wer, 1S yy,
  • 145. Step 2 — In the next screen, enter the Item name, in this case we have named it Helloworld. Choose the “Freestyle project option’ Step 3 — We need to specify the location of files which need to be built. Click on the Git option and enter the URL of the local git repository. If it is local repository then mention local repository folder path. Step 4 — Now go to the Build section and click on Add build step — Execute Windows batch command Step 5 — In the command window, enter the commands which you want to execute and then click on the Save button. Step 6 — Once saved, you can click on the Build Now option to see if you have successfully defined the job.
  • 146. Jenkins Distributed Architecture Jenkins uses a Master-Slave architecture to manage distributed builds. In this architecture, Master and Slave communicate through TCP/IP protocol. Jenkins Master Your main Jenkins server is the Master. The Master’s job is to handle: = Scheduling build jobs. = Dispatching builds to the slaves for the actual execution. = Monitor the slaves (possibly taking them online and offline as required). =" Recording and presenting the build results. = A Master instance of Jenkins can also execute build jobs directly.
  • 147. Jenkins Slave A Slave is a Java executable that runs on a remote machine. Following are the characteristics of Jenkins Slaves: It hears requests from the Jenkins Master instance. Slaves can run on a variety of operating systems. The job of a Slave is to do as they are told to, which involves executing build jobs dispatched by the Master. You can configure a project to always run on a particular Slave machine, or a particular type of Slave machine, or simply let Jenkins pick the next available Slave. Jenkins Master will distribute its workload to the Slaves Neate ete & Jenkins Slave yr Jenkins Slaves are generally required to provide the desired environment. It works on the basis of requests received from Jenkins Master.
  • 148. > Now let us look at an example in which Jenkins is used for testing in different environments like: Ubuntu, MAC, Windows etc. The diagram below represents the same: Code commit triggers Continuous Integration Jenkins Server (Master) GitHub repository TCP/IP TCP/IP TCP/IP atta diab aerate arava aia Slave Slave yr W a) cE, Ay & sa The following functions are performed in the above image: Jenkins checks the Git repository at periodic intervals for any changes made in the source code. Each builds requires a different testing environment which is not possible for a single Jenkins server. In order to perform testing in different environments Jenkins uses various Slaves as shown in the diagram. Jenkins Master requests these Slaves to perform testing and to generate test reports. yy,
  • 149. References = Continuous Integration — Martin Fowler = http://www.martinfowler.com/articles/continuousIntegration. html =# Hudson = http://hudson-ci.org/ = Hudson Continuous Integration Server = http://www.code- magazine.com/articleprint.aspx?quickid=090607 1 &printmode=true = The Hudson Book = http://www.eclipse.ore/hudson/the-hudson-book/book-hudson. pdf = Jenkins = https://wiki.jenkins-ci.org = Monkey Image = http://corrines-cormer2006. blogspot.com/2011/09/freebie-monday_26.html = What is Continuous Integration = http://confluence.public.thoughtworks.oreg/display/CCNET/Whattis+Continuous » +Integration
  • 150. Types of Jenkins Projects simple, single tasks whole delivery cycle e.g. run tests e.g. test | build | .. like pipeline for a single br 1 for m
  • 151. @ Jenkins Jenkins + Credentials + System 4 Back to credential domains @= Add Credentials Global credentials (unrestricted) + Kind | Username with password Scope | Gilobal (Jenkins, nodes, items, all child items, etc) ]@ * Username & ® Password ) @ Credential Scopes System == Only available on Jenkins server NOT for Jenkins jobs Global mn Everywhere accessible
  • 152. es LL Jenkins + Credentials + System + Global credentials (unrestricted) 4# Back to credential domains her Username with password en me ey @= Add Credentials a * Lelia od at Pacerfe ude tielt eS 6 Certificate ® @ Username & Password Certificate Secret File
  • 153. @ Jenkins Jenkins » Credentials » System + Global credentials (unrestricted) » * Back to credential domains ina ec es) @= Add Credentials Perea : 7 @ tee X.509 Client Certificate es © eateries Username & Password New types based on plugins Certificate Secret File
  • 154. > Jenkins ikins Credentials System Global credentials (unrestricted) Back to credential domains Kind Username with password » Add Credentials Scope Global (Jenkins, nodes, items, all child items, etc) Username global Password... sad glob Description ID = Reference for your credentials
  • 155. @ Jenkins search Jenkins Credentials System Global credentials (unrestricted) > Back to credential domains @= Add Credentials oy Global credentials (unrestricted) Credentials that should be available irrespective of domain specification to requirements matching. Name Kind Descripti a globai/****** Username with password Icon: SML
  • 156. @ Jenkins Jenkins Credentials System + Back to credential domains @= Add Credentials Global credentials (unrestricted) Kind Username with password Scope System (Jenkins and nodes onty) Username system Password ||. ” system Description a search
  • 157. Jenkins Credentials System Global credentiais (unrestricted) * Back to Sredential domains @ Add Credentials fy Global credentials (unrestricted) Credentials that should be available irrespective of domain specification to requirements matching. Name Kind Descripti A global"***"" Username with password A ser Username with password Icon: SML
  • 158. @ Jenkins Jenkins my-pipeline # Up WA, Status % Configure f@ Scan Multibranch Pipeline Log Qe Multibranch Pipeline Events © Delete Multibranch Pipeline & People 7 Build History ‘1. Project Relationship = Check File Fingerprint 2 Rename oO Pipeline Syntax A Credentials Be Now vi Build Queue No builds in the queue. (~-) my-pipeline This folder is empty There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects in branches that contain recognizable projects. Pipeline Branch projects support building branches within a repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This file should contain a valid Jenkins Pipeline. See also: Creating Multibranch Projects. Configure the project for a buildable repository or re-index branches if the repository has since been configured.
  • 159. @ Jenkins Jenkins my-pipeline f Ue . Status Z Configure §@ Scan Multibranch Pipeline Log GS Multibranch Pipeline Events (x) Delete Multibranch Pipeline & People @ Build History . Project Relationship $= Check File Fingerprint 2 Rename 0 Pipeline Syntax A Credentials Da Now Vi Build Queue No builds in the queue esp my-pipeline This folder is empty There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects in branches that contain recognizable projects. Pipeline Branch projects support building branches within a Credential Scopes System == Only available on Jenkins server LOR Me te)ae Cal diate) Global == Everywhere accessible
  • 160. @ Jenkins Jankins my-pipeline Credentials # Up O. Status # Configure §@ Scan Multibranch Pipeline Log Multibranch Pipeline Events © Delete Multibranch Pipeline a People “= Bulld History “A. Project Relationship 4— Check File Fingerprint ‘> Rename oO Pipeline Syntax A. cr a Folder fi New View Bu il helbbhti A Credentials ar P Store | A, 4 Jenkins lcoon: SML Stores scoped to my-pipeline P Store | Qe y-nineline (global) Stores from parent P Store | 2 Jenkins (global) (global) Domain global ID Domains Domains seeeee
  • 161. @ Jenkins Jenkins » my-pipeline + Credentials Up (. Status Z Configure §@ Scan Multibranch Pipeline Log Project A Credentials T P Store | Domain ID Credential Scopes =— Limited to project, ONLY with multibranch pipeline
  • 162. x Configure Ba Scan Multibranch Pipeline Log oS Multibranch Pipeline Events © Delete Multibranch Pipeline & People “& Build History O, Project Relationship 4= Check File Fingerprint — a Rename oO Pipeline Syntax a Credentials | Folggr fi New View ie P Store | Domain A, | sentins (global) Icon: SML Stores scoped to my-pipeline P Store | [A m-ripwiine i& (global) Stores from parent P Store | G senkins és (global)
  • 163. K Configure @ Scan Multibranch Pipeline Log & Multibranch Pipeline Events © Delete Multibranch Pipeline &, People > Build History OX Project Relationship 4— Check File Fingerprint 2 Rename 0 Pipeline Syntax A. Credentials 7 P Store | | .S & Jenkins (global) Icon: SML Stores scoped to my-pipeline ?P Store | [Qi m-nipeline i (global) Stores from parent Bp Stare | enables to organize build jobs in folders __,..1,. Domain
  • 164. Saale Jenkins my-pipeline Credentials # Back to credential domains @= Add Credentials Folder Global credentials (unrestricted) Kind Username with password Username riappiceine Password eeererereee 2 my-pipeling Description Ea,
  • 165. @ Jenkins are Jenkins my-pipeige - Credentials Folder Global credentials (unrestricted) > Back to credential domains @= Add Credentials ey Global credentials (unrestricted) Credentials that should be available irrespective of domain specification to requirements matching. Name Kind Description a my-pineling/****** Username with password 2 icon: SML
  • 166. @ Jenkins Jenkins + my-pipeline Credentials ® Up ‘ OX Status @. Credentials #. Configure §@ Scan Multibranch Pipeline Log : eens ovine = = £2 Muttibranch Pipeline Events a 4 — (global) gobel global i) Delete Multibranch Pipeline A A my-pipeline * (global) my-pipeline my-pipeline****** & People Icon: SML ee Sule Hietory Stores scoped to my-pipeline . Project Relationship Pp Store | Domains >) Check File Fingerprint a 4 my-pinaline wi (global) we Rename oO Pipeline Syntax Stores from parent A. Credentials P Store | Samus 4 Folder z Jenkins ith (global) fm New View Build Queue =
  • 167. Cereb it Jenkins my-pipeline Credentials # Up Status #. Configure la Scan Multibranch Pipeline Log Multibranch Pipeline Events © Delete Multibranch Pipeline & People “> Build History , Project Relationship 4 Check File Fingerprint “= Rename oO Pipeline Syntax i Credentials q Folder [i New View Build Queve No builds in the queue. A. Credentials Tr, Pp Store | Domain A 4 enking (global) iobal .. BB ~-nineline (global) trrlpipeline Icon: SML Stores scoped to my-pipeline P Store | A my-pipeline wh (global) Stesattonmmarscs » System credential NOT accessible here! Q enkins i (global) Domains Domains global/**"** my-pipeline/**"""""
  • 168. @ Jenkins Qsoarch Jenkins All Enter an item name test! This is the central feature of Jenkins. Jenkins will build your project, combining any SCM with any build system, and this can be even used for something other than software build Pipeline r / Orchestrates long-running activities that can span multiple build agents. Suitable for building pipelines (formerly known as workflows) and/or organizing complex activities that do not easily fit in free-style job type. _ Multi-configuration project es | Suitable for projects that need a large number of different configurations, such as testing on multiple environments, platform-specific builds, etc. Folder Creates a container that stores nested items in it. Useful for grouping things together. Unlike view, which is just a filter, a folder creates a separate " famespace, so you can have multiple things of the same name as long as they are in different folders. » GitHub Organization PMMA Srans a GitHih amanization far user acenunt for all rannsitarias matchinn same definad markers
  • 169. Jenkins + All Multi-configuration project Suitable for projects that need a large number of different configurations, such as testing on multiple environments, platform-specific builds, etc. ) Folder Creates a container that stores nested items in it. Useful for grouping things together. Unlike view, which is just a filter, a folder creates a separate namespace, so you can have multiple things of the same name as long as they are in different folders. GitHub Organization » Scans a GitHub organization (or user account) for all repositories matching some defined markers. GitHub Organization » Scans a GitHub organization (or user account) for all repositories matching some defined markers. Multibranch Pipeline / Creates a set of Pipeline projects according to detected branches in one SCM repository. If you want to create a new item from other existing, you can use this option: eo Copy from | Type to autocomplete
  • 170. Jenkins » test » # Up O Status #. Configure a Scan Multibranch Pipeline Log GE Multibranch Pipeline Events © Delete Multibranch Pipeline & People @ Build History OA, Project Relationship 4%) Check File Fingerprint > Rename oO Pipeline Syntax Srey fi New View This folder is empty There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects in branches that contain recognizable projects. Pipeline Branch projects support building branches within a repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This file should contain a valid Jenkins Pipeline. See also: Creating Multibranch Projects. Configure the project for a buildable repository or re-index branches if the repository has since been configured.
  • 171. @ Jenkins Credentials Jenkins test # Up OL Status #. Configure §@ Scan Multibranch Pipeline Log Multibranch Pipeline Events © Delete Multibranch Pipeline & People > Build History . Project Relationship 4>) Check File Fingerprint 2 Rename © Pipeline Syntax “A. Credentials P & @ er Icon: SML Store | Stores scoped to test Pp Q xs Store | Stores from parent P 4 Jenkins Store | i& (global) i& (global) (global) Domain global Domains Domains
  • 172. - first syntax Cg node { // groovy script] }
  • 173. Y dev / Jenkinsfile pipeline { Tey ULC) MARE agent any - Groovy TEL stages { - easier to get started, PTET Ry stage("build”) { NEUE Ci LT steps { - difficult to sta .
  • 174. Y dev / Jenkinsfile bi peline { - first syntax SHAE ECL agent any e PAY PTT i) stages { = easier to get started, stage("build") { but not that powerful Woman nuwhWwne steps { Sie CHES AiG Mase , } } |
  • 175. Y dev / Jenkinsfile pipeline { agent any stages { stage("build") f{ steps { } phde { // groovy script
  • 176. ¥Y dev / Jenkinsfile kbipeline { agent any stageC("build") f{ 1 2 3 4 5 stages { 6 7 8 steps { } node { // groovy script }
  • 177. Y dev / Jenkinsfile = a SM TAM Gn ea ay pipeline { I eT CRC agent any| stages { stage("build") { steps { } node { // groovy script }
  • 178. Y dev / Jenkinsfile “ ~ MAT Mea ie aa pipeline { me Me Ca agent any stages { Se TM mmm Te Mer dbs stage("build") f steps { } } ae } node { // groovy script }
  • 179. Y dev / Jenkinsfile Pt - - “pipeline” must be top-level pipeline { me TM) CRTC agent any stages: 1 SCC TMC mM MT hy stage("build") { steps { = ae eT and “steps” } node { // groovy script }
  • 180. Y dev / Jenkinsfile fs Select a template type 1 pipeline { 2 3 agent any 4 5 stages { 6 7 stageC("build") { 8 9 steps { 10 11 } 12 } 13 14 stage("test") { 15 16 steps { 17 18 } 19 } 20 21 stage("deployf') { 22 23 steps { I 24 25 }
  • 181. F OUev f/f JENKLINSTLLe w Select a template type 1 2 3 4 5 6 7 8 ts] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 22 PR pipeline { agent any stages { stageC"build") { steps { } } stage("test") { steps { } } stage("deploy") { steps { }
  • 182. Nn @ Ydev / Jenkinsfile FS Selecta template type ~ 1 2 3 4 5 6 7 8 te) 10 11 12 13 14 15 16 LZ 18 19 20 21 22 23 24 25 26 27 pipeline { agent any stages { stage("build") { steps { echo ‘building the application...‘ } } stage("test") { steps { echo 'testing the application..." } } stage("deploy") { steps { echo 'deplying the application...' } i
  • 183. Lo ig 20 21 23 24 25 26 27 28 29 } stage("deploy") { steps { } echo 'deplying the application... | Commit message Add Jenkinsfile Target Branch dev Orel tial moral laren
  • 185. & Jenkins Jenkins my-pipeline ® Up A. Status 7 Configure (&) Scan Muttibranch @speline Now | Scan Multibranch Pipeline Log cS Multibranch Pipeline Events © Delete Multibranch Pipeline & People ~ Build History A, Project Relationship &= Check File Fingerprint “@ Rename ©) Pipeline Syntax @. Credentials | Mmy-pipeline This folder is empty There are no branches found thal contain buildable projects. Jenkins automatically builds and manages projects in branches that contain recognizable projects. Pipeline Branch projects support building branches within a repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This {ile should contain a valid Jenking Pipeling. See also: Creating Multibranch Projects Configure the project for a buildable repository or re-index branches if the repository has since been configured
  • 186. Sol ehi ts JO@NKING my-pipeline ® Up QL Status 7 Configure & Scan Multipranch Pipeline Now td Sq Done. PELO9 oe Multibranch Pipeline Events © Delete Multibranch Pipeline & People @ Build History A. Project Relationship 4= Check File Fingerprint “= Rename © Pipeline Syntax &. Credentials -~. my-pipeline This folder is empty There are no branches found that contain buildable projects. Jenkins automatically builds and manages projects in branches that contain recognizable projects. Pipeline Branch projects support building branches within a repository containing a pipeline script. Per default it uses a file named Jenkins file in the root directory. This file Should contain a valid Jenkins Pipeline. See also: Creating Multibraneh Projects. Conhgure the project for a buildable repository or re-index branches if the repository has since been configured
  • 187. Jenkins + my-pipeline » Scan Multibranch Pipeline aH Configure (2) Scan Multibranch Pipeline Now §@ Scan Multibranch Pipeline Log © View as plain text a Multibranch Pipeline Events © Delete Muttibranch Pipeline & People ‘> Build History QO, Project Relationship 4>) Check File Fingerprint in Rename © Pipeline Syntax ” Credentials fi New View Build Queue Started by user jenkins [Fri Feb 07 05:34:12 UTC 2020] Starting branch indexing... > git --version # timeout=10 using GIT_ASKPASS to set credentials > git ls-remote --symref -- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git # timeout=. > git rev-parse --is-inside-work-tree # timeout=10 Setting origin to https://gitlab.com/nanuchi/techwor]d-js-docker-demo-app.git > git config remote.origin.url https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git # timeor Fetching & pruning origin... Listing remote references... > git config --get remote.origin.url # timeout=10 > git --version # timeout=10 using GIT_ASKPASS to set credentials > git ls-remote -h -- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git # timeout=10 Fetching upstream changes from origin > git config --get remote.origin.url # timeout=10 using GIT_ASKPASS to set credentials > git fetch --tags --progress --prune -- origin +refs/heads/*:refs/remotes/origin/* # timeout=10 Checking branches... Checking branch master *Jenkinsfile’ not found Does not meet criteria Checking branch feature-one “Jenkinsfile’ not found Does not meet criteria Checking branch dev ‘Jenkinsfile’ found Ses SSS
  • 188. > git rev-parse --is-inside-work-tree # | Ge Multibranch Pipeline Events Setting origin to https://gitlab.com/nanu: > git config remote.origin.url https://q, © Delete Multibranch Pipeline Fetching & pruning origin... Listing remote references... a, People > git config --get remote.origin.url # t: > git --version # timeout=10 —s ‘i wt Build History using GIT ASKPASS to set credentials O Project Relationship > git ls-remote -h -- https://gitlab.com Fetching upstream changes from origin 4= Check File Fingerprint > git config --get remote.origin.url # t. -_ using GIT_ASKPASS to set credentials = Rename > git fetch --tags --progress --prune -- Checking branches... 0 Pipeline Syntax Checking branch master f . ‘Jenkinsfile’ not found * STATE Does not meet criteria Ga New View Checking branch feature-one ‘Jenkinsfile’ not found Build Queue a Checking branch dev No builds in the queue. Met criteria Processed 4 branches Build Executor Status = [Fri Feb 07 05:34:15 UTC 2020] Finished b: Finished: SUCCESS
  • 189. Gi search @ Jenkins Jenkins my-pipeline # Up t A, Status Z Configure &) Scan Multibranch Pipeline Now §@ Scan Multibranch Pipeline Log Multibranch Pipeline Events © Delete Multibranch Pipeline &, People @ Build History (. Project Relationship 4>) Check File Fingerprint - Rename oO Pipeline Syntax A. Credentials (. my-pipeline - abt Branches (1) s @ Icon: SML Ww 4 Name | cu,” Last Success 21 sec - #1 Last Failure Last NIA 205 Legend fj Atom feed forall [J Atom feed for
  • 190. @ Jenkins Jenkins my-pipeline dev ® Up . Status ~~ Changes ©) Build Now ¥% View Configuration . Full Stage View © Pipeline Syntax .) Build History trend == find @ #1 Feb 7, 2020 5:34 AM Atom feed for all E Atom feed for failures Pipeline dev Full project name: my-pipeline/dev Stage View 2g Recent Changes eet Feb 07 06:34 Declarative: Checkout SCM 16s 16s build 50ms test 44ms Qi search deploy 30ms 30ms
  • 191. | @ Jenkins Jenkins my-pipeline dev ® Up O. Status = Changes ) Build Now tt View Configuration . Full Stage View ©) Pipeline Syntax _) Build History trend = find ou Feb 7, 2020 5:34 AM Atom feed for all BY Atom feed for failures Qisearch Pipeline dev Full project name: my-pipeline/dev preerry > A Recent Changes Stage View Declarative: Checkout SCI . build test deploy 165 50ms 44ms 30ms ei : 16s 50ms 44ms 30ms 06:34 -
  • 192. @ Jenkins Jenkins my-pipeline dev Up . Status “= Changes ©) Build Now Fs View Configuration ‘2, Full Stage View © Pipeline Syntax ) Build History trend == find w@ #1 Feb 7, 2020 5:34 AM Atom feed for all F) Atom feed for failures Pipeline dev Full project name: my-pipeline/dev Rik 2 Recent Changes ——n Stage View Declarative: Success test deplo Checkout SCM ad 168 44ms 30ms Feb 07 16s " a 06:34 Mines ali nde
  • 193. Stage Logs (build) ©Print Message — building the application... (self time 4ms) building the application...
  • 195. @ Jenkins Jenkins my-pipeline dev % Up O. Status > Changes © Build Now tt View Configuration OX Full Stage View © Pipeline Syntax Build History find eu Feb 7, 2020 5:34 AM Atom feed for all ©) Atom feed for failures Pipeline dev Full project name: my-pipeline/dev = Recent Changes ee Stage View Feb 07 06:34 Permalinks Success Jf | 16s build 50ms test 44ms 44ms or ‘A search deploy 30ms 30ms
  • 196. Stage Logs (Declarative: Checkout SCM) © Check out from version control (self time 16s) using credential demo-app-git-credentials Cloning the remote Git repository Cloning with configured refspecs honoured and without tags Cloning repository https://qitlab. com/nanuchi/techword-js-docker-demo~app.git > git init /var/jenkins_home/workspace/my-pipeline_dev # timeout=10 Fetching upstream changes from https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git > git —-version # timeout=10 using GIT_AYKPASS to set credentials > git fetch --no-tags --progress -- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url https://gitlab. com/nanuchi/techworld-js-docker-demo-app.git # tim eout=10 > git config —add remote.origin. fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url https://git lab. com/nanuchi/techworld-js—docker-demo-app.git # tim eout=10 Fetching without tags Fetching upstream changes from https://gitlab.com/nanuchi/techword-js-docker-demo-app.git using GIT_ASKPASS to set credentials > git fetch —no-tags —progress —- https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git __
  • 197. Qa search Jenkins my-pipeline # Up . Status Z Configure @) Scan Multibranch Pipeline Now §@ Scan Multibranch Pipeline Log Multibranch Pipeline Events & Delete Multibranch Pipeline &} People > Build History . Project Relationship 4— Check File Fingerprint = Rename oO Pipeline Syntax @. Credentials (~)) my-pipeline wk Branches (1) s Ww ¥ , Icon: SML Name | dev Last Success 1 min 11 sec - #71 Last Failure Li N/A 2 Legend jj Atom feed for all Gj Atom feed for
  • 198. Cc @ localhost Jenkins » my-pipeline General Branch Sources Build Configuration Scan Multibranch Pipeline Triggers Orphaned Item Strategy Health metrics Properties Pipeline Libraries Pipeline Model Definition Branch Sources Git Project Repository https://gitlab.com/nanuchi/techworld-js-docker-demo-app.git ® Credentials nn_janashia@yahoo.com/*****" 4 @» Add + ® Behaviours Discover branches Filter by name (with regular expression) Regular expression “devimasterlfeature.*S ® Add ~ Property strategy All branches get the same properties ar
  • 199. @ Jenkins Jenkins my-pipeline dev ® Up (OQ. Status "> Changes &) Build Now es View Configuration . Full Stage View © Pipeline Syntax -) Build History trend = find i #1 Feb 7, 2020 5:34 AM Atom feed for all Fj Atom feed for failures Pipeline dev Full project name: my-pipeline/dev snot e Recent Changes : J Stage View Decidrative: Checkout SCM 16s Feb 07 . 1 6s 06:34 Permalinks build 50ms test 44ms 44ms QA search deploy 30ms 30ms
  • 200. Test changes in a Jenkinsfile —
  • 201. | @ Jenkins Qa search Jenkins my-pipeline # Up O. Status Z Configure &) Scan Multibranch Pipeline Now §@ Scan Multibranch Pipeline Log G Multibranch Pipeline Events © Delete Multibranch Pipeline &, People “> Build History ©. Project Relationship 4>) Check File Fingerprint = Rename oO Pipeline Syntax a Credentials (-<) my-pipeline ae Branches (1) s WwW ¥ -) Icon: SML Name | Last Success 5 min 31 sec - #1 Last Failure Li N/A 2 Legend {J Atom feed forall J Atom feed for
  • 202. a ~~ om iv @ The file has been successfully created. (2) Jenkinsfile 464 Bytes [6 Adjust Jenkinsfile pipeline { agent any stages { PTET IN I stage("build") { @ steps { ho ‘building the applicat ° , SS en ee arte Ch } - @ tea TTL stage("test") {
  • 203. @ Jenkins search Jenkins my-pipeline dev #® Up . ' Pipeline dev . Status a Full project name: my-pipeline/dev Changes a @) Build Now a Recent Changes amen es View Configuration O. Full Stage View Stage View © Pipeline Syntax Declarative: Checkout SCM build test deploy -) Build History trend = 165 50ms 44ms 30ms i el find ' ' i eu Feb §, 020 5:54 AM © € Feb 07 Atom feed for all 5) Atom feed for failures obe4 = => =| fe fs 5 30ms Permalinks
  • 204. @ Jenkins Q search Jenkins my-pipeline dev #1 # Back to Project OQ, Status @ Build #1 (Feb 7, 2020 5:34:15 AM) - Changes £@ Console Output > Edit Build information a Branch indexing © Delete build #1" Revision: a7f8 1ded96a13e1606bb72c085e4d6118bdde1 ad « dev @ Git Build Data ® git GJ No Tags @ Restart from Stage © &pplay ~ Pipeline Steps fi Workspaces
  • 205. rs Jenkins Qa search Jenkins my-pipeline dev #1 Replay ® Back to Project Replay #1 ©, Status * Pee Allows you to replay a Pipeline build with a modified script. If any Load steps were run, you can also modify the scripts they loaded. = Changes Main Script l~ pipeline { [3 Console Output 2 — 3 agent any Edit Build Information 4 5° stages { © Delete build ‘#1’ 6 7- stage("“build") { } Git Build Data 8 9 steps { GJ No Tags 10 echo ‘building the application...’ 11 } @ Restart from Stage 12 } 13 a Replay 14- stage("test") { 15 Pipeline Steps ns Pipeline Syntax [i Workspaces
  • 206. gz Jenkins Qisearch Jenkins my-pipeline dev #1 Replay > Back to Project Replay #1 Allows you to replay a Pipeline build with a modified script. If any load steps were run, you can also modify the scripts they loaded. . ‘A. Status > Changes Main Script l= pipeline { §@ Console Output ; — 3 agent any ea Edit Build Information 4 5° stages { ©& Delete build #1" 6 7+ stage("build") { } Git Build Data 8 9- steps { I Gl No Tags 10~ script { 11 | @ Restart from Stage 12 } 13 } & Replay 14 } 15 Pipeline Steps oe Pipeline Syntax (} Workspaces
  • 207. ay J e nki beh) Q search Jenkins my-pipeline dev #1 Replay # Back to Project Replay #1 . Status a Allows you to replay a Pipeline build with a modified script. If any Load steps were run, you can also modify the scripts they loaded. we Changes Main Script 6 wf Console Output 7> stage("build”) { 8 > Edit Build Information 9~ steps. { = 10 echo ‘building the application...' © Delete build #1" 11 12 ~ script { } Git Build Data 13 def test = 2+ 2> 37? ‘cool’ : 'not cool" 14 echo test GJ No Tags 15 } 16 } ® Restart from Stage 17 } 18 ad Replay 19 = stage("test") { 20 Pipeline Steps aaa ctone_f Pipeline Syntax fi Workspaces
  • 208. @ Jenkins Jenkins my-pipeline dev # Up . Status “> Changes © Build Now t View Configuration Full Stage View h © Pipeline Syntax -) Build History trend <= find @ #1 Feb 7, 2020 5:34 AM Atom feed for all ©) Atom feed for failures -— = Pipeline dev Full project name: my-pipeline/dev ‘auououse = Recent Changes — Stage View Feb 07 06:46 Feb 07 06:34 Declarative: Checkout SCM 165 16s build 50ms test 44ms AQ search deploy 30ms 30ms
  • 209. @ Jenkins Jenkins my-pipeline dev # Up . Status 2 Changes ) Build Now tt View Configuration , Full Stage View © Pipeline Syntax + Build History trend = find @ #2 Feb 7, 2020 5:48 AM w@ #1 Fab 7, 2020 5:47 AM Atom feed for all 3} Atom feed for failures Pipeline dev Full project name: my-pipeline/dev ‘ouout 2g" Recent Changes ot Stage View Feb 07 06:48 eB Feb 07 06:47 Declarative: Success Checkout SCM 6s | io ea | 1 J gg 870ms 7ims tis 4oms test 32ms Qa search deploy 3ims 32ms
  • 210. Stage Logs (build) © Print Message — building the application... (self time 4ms) building the application... k © Print Message — cool (self time 3ms)
  • 213. ripeine aev Full project name: my-pipeline/dev OY Status 7 Changes saaaaeti §@) Build Now [aa Recent Changes tt View Configuration OY Full Stage View Stage View oO Pipeline Syntax Declarative: ct SCM build test deploy Build History trend = Average stage times: 6s 55ms sems aims find x (Average full runtime: 8s .?_—_—==[[—_u—= « . — = a en Feb 7, 2020 5:48 AM ee. | Feb 07 No en Feb 7, 2020 5:47 AM = Changes 870ms 71ims 34ms 31ms | =e o-- | _feed for failures @& —— a Console Output | Febo7 | C = 1is 40ms 3ims 32ms > Edit Build Information a © Delete build ‘#2 >} Git Build Data Permalinks Gl No Tags * Last build (#2), 13 ms ago * Last sable bulk (41). 1 min0 sec 90 Restart from Stage fi @ Pore tom rege | * (cicaeieitieris abel alindeemaamy
  • 214. OY Status a Changes ® Build Now tt View Configuration O, Full Stage View oO Pipeline Syntax _) Build History find @ #2 eH Feb 7, 2020 5:48 AM Feb 7, 2020 5:47 AM oa -_ a fa Console Output _ j = Edit Build Information 8 Delete build '#2” eh Git Build Data Gl No Tags feed for failures ripeine aev Full project name: my-pipeline/dev [aif Reson Chances Stage View Average stage times: (Average full run time: ~8s) No | Feb 07 | Changes 06:48 Permalinks Last build (#2), 13 ms ago ! build (#4 870ms lis build 55ms 7ims 40ms 32ms 34ms. aims. deploy 31ims 31ims 32ms jak ee a Ee Lae ee min * iaukone tik banalete 1 min 0 sec aao
  • 215. Jenkins » my-pipeline +» dev +» #2 » Restart from Stage 4 Back to Project OY Status = Changes Restart #2 from Stage ae ULe re ct aan deploy {@ Console Output 2a Edit Build Information © Delete build ‘#2’ ©} Git Build Data tJ No Tags @ Restart from Stage @ Replay - 2 Pineline Stance
  • 216. Jenkins # Up » my-pipeline +» dev + OY Status > Changes ® Build Now Fed View Configuration OY Full Stage View © Pipeline Syntax _) Build History trend = find x eu Feb 7, 2020 5:50 AM @ #2 Feb 7, 2020 5:48 AM oH Feb 7, 2020 5:47 AM 3) Atom feed for all J Atom feed for failures Pipeline dev Full project name: my-pipeline/dev ada =a? Recent Changes a Stage View Feb 07 No | Changes 06:50 Febo7 | No | Changes 06:48 | Febo7 | Ne i nn-a?T Declarative: Checkout SCM 4s 858ms 870ms lis build 55ms 7ims 40ms 32ms 34ms gims deploy 34ms 39ms aims 32ms
  • 217. Jenkins & Up Q Status 7 Changes my-pipeline +» dev & Build Now & View Configuration OY Full Stage View o Pipeline Syntax _» Build History find @#8 ef eH Feb 7, 2020 5:50 AM Feb 7, 2020 5:48 AM Feb 7, 2020 5:47 AM fS) Atom feed for all Ey Atom feed for failures Pipeline dev Full project name: my-pipeline/dev didenooe ag Recent Changes bee Stage View Feb 07 06:50 Feb 07 06:48 Febo7 | No N6:AT Skips the other stages Declarative: Checkout SCM 4s 858ms 870ms lis build 55ms 71ms 40ms test 32ms 34ms Sims deploy 34ms 39ms 3ims 32ms