The basic unit of any Angular Application is the component

This post summaries the common tasks with components and can be used as a pool of useful code snippets

Creating

Data binding – one way and 2-way

Using ngIf and ngFor to create dynamic template content

creating and communicating with nested components

Creating a new Angular App

# ng new CompTests # cd CompTests # ng serve 1 2 3 # ng new CompTests # cd CompTests # ng serve

The generated a simple app with one main component and one module:

app.module.ts – the main module class

app.component.ts – the parent component code

app.component.html – the parent component template

app.component.css – the parent component styles

Integrating Twitter bootstrap

# npm install bootstrap --save 1 # npm install bootstrap --save

now open the file .angular-cli.json (in the project root directory) and add the bootstrap css to the styles section:

"styles": [ "styles.css", "../node_modules/bootstrap/dist/css/bootstrap.css" ], 1 2 3 4 "styles" : [ "styles.css" , "../node_modules/bootstrap/dist/css/bootstrap.css" ] ,

restart the web server to see the result (Ctrl + c , ng serve)

Adding Forms Module

To use forms components you need to import the Forms Module, add the following code to the main app module (app.module.ts)

import {FormsModule} from "@angular/forms"; imports: [ BrowserModule, FormsModule, … 1 2 3 4 5 6 import { FormsModule } from "@angular/forms" ; imports : [ BrowserModule , FormsModule , …

DataBinding

One way – from code to template

Interpolation – code:

num:number = 10; 1 num : number = 10 ;

template:

{{ num }} , {{ num*10 }} 1 { { num } } , { { num * 10 } }

Property binding – code:

num1:number = 100; col:string = “red”; sz:number = 20; 1 2 3 num1 : number = 100 ; col : string = “ red ” ; sz : number = 20 ;

template:

<input [value]=’num1’ /> <label [style.color]="col" [style.font-size.px]="sz">Hi</label> 1 2 < input [ value ] = ’ num1 ’ / > < label [ style . color ] = "col" [ style . font - size . px ] = "sz" > Hi < / label >

Note that the following 2 ways have the same results:

<input [value]=’num1’ /> <input value={{num1}} /> 1 2 < input [ value ] = ’ num1 ’ / > < input value = { { num1 } } / >

One way – from the template to the code

Events and event handlers

Button click event

<button (click)=”f1()”>click</button> 1 < button ( click ) = ” f1 ( ) ” > click < / button >

Code:

f1(){ console.log(‘button click’); } 1 2 3 f1 ( ) { console . log ( ‘ button click ’ ) ; }

Input key event

<input (keypress)=”f2()”/> 1 < input ( keypress ) = ” f2 ( ) ” / >

you can send the event object using $event:

<input (keypress)=”f2($event)”/> 1 < input ( keypress ) = ” f2 ( $ event ) ” / >

Code:

f2(ev){ console.log(‘key press’ + ev.key); } 1 2 3 f2 ( ev ) { console . log ( ‘ key press ’ + ev . key ) ; }

you can send any data you like – for example calculator buttons calling the same event with different values:

<button (click)="cl(1)">1</button> <button (click)="cl(2)">2</button> … <button (click)="cl(9)">9</button> 1 2 3 4 < button ( click ) = "cl(1)" > 1 < / button > < button ( click ) = "cl(2)" > 2 < / button > … < button ( click ) = "cl(9)" > 9 < / button >

2-way data-binding

textbox

<input [(ngModel)]=’num2’ /> 1 < input [ ( ngModel ) ] = ’ num2 ’ / >

Code:

num2:numer = 90; 1 num2 : numer = 90 ;

Checkbox

<input type="checkbox" [(ngModel)]="bl" value="Checkbox"> 1 < input type = "checkbox" [ ( ngModel ) ] = "bl" value = "Checkbox" >

Code:

bl:boolean; 1 bl : boolean ;

select

<select [(ngModel)]="Item"> <option *ngFor="let item of Items" [value]="item.id"> {{item.name}} </option> </select> 1 2 3 4 5 6 < select [ ( ngModel ) ] = "Item" > < option * ngFor = "let item of Items" [ value ] = "item.id" > { { item . name } } < / option > < / select >

Code:

export interface Item { id: number; name: string; } // in the component class code: Item: number; Items: Item[] = [ { name : 'liran', id: 100 }, { name : 'avi', id: 200 }, { name : 'dani', id: 300 }, ]; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export interface Item { id : number ; name : string ; } // in the component class code: Item : number ; Items : Item [ ] = [ { name : 'liran' , id : 100 } , { name : 'avi' , id : 200 } , { name : 'dani' , id : 300 } , ] ;

Built in directives

If Statement

<div *ngIf="num3 % 2 == 0">{{num3}}</div> 1 < div * ngIf = "num3 % 2 == 0" > { { num3 } } < / div >

displays the content of num3 if the condition is true, otherwise displays nothing

if-else

<div *ngIf="num2 % 2 == 0; else errmsg"> Condition is true! </div> <ng-template #errmsg> Condition is false! </ng-template> 1 2 3 4 5 6 < div * ngIf = "num2 % 2 == 0; else errmsg" > Condition is true ! < / div > < ng - template #errmsg> Condition is false ! < / ng - template >

2 templates

<div *ngIf="cond ; then tmpl1 else tmpl2"></div> <ng-template #tmpl1> Correct! </ng-template> <ng-template #tmpl2> Wrong! </ng-template> 1 2 3 4 5 6 7 8 9 < div * ngIf = "cond ; then tmpl1 else tmpl2" > < / div > < ng - template #tmpl1> Correct ! < / ng - template > < ng - template #tmpl2> Wrong ! < / ng - template >

For Statement

Create a list of template elements

Put the ngFor on the element you want to duplicate

Iterate over a data structure (array or any collection)

Code:

items: string[] = ['avi','dani','yosi']; 1 items : string [ ] = [ 'avi' , 'dani' , 'yosi' ] ;

template:

<ul *ngFor="let item of items"> <li>{{item}}</li> </ul> 1 2 3 < ul * ngFor = "let item of items" > < li > { { item } } < / li > < / ul >

Add index to each item:

<ul *ngFor="let item of items; let i = index" [attr.data-index]="i"> <li>{{item}}</li> </ul> 1 2 3 < ul * ngFor = "let item of items; let i = index" [ attr . data - index ] = "i" > < li > { { item } } < / li > < / ul >

Simple loop, fixed size

<ul> <li *ngFor="let number of [0,1,2,3,4]">{{number}}</li> </ul> 1 2 3 < ul > < li * ngFor = "let number of [0,1,2,3,4]" > { { number } } < / li > < / ul >

Simple Loop, dynamic size

constructor() { let size=10; this.ar = Array(size).fill(0).map((x,i)=>i); } ar:number[]; 1 2 3 4 5 constructor ( ) { let size = 10 ; this . ar = Array ( size ) . fill ( 0 ) . map ( ( x , i ) = > i ) ; } ar : number [ ] ;

Template:

<li *ngFor="let number of ar">{{number}}</li> 1 < li * ngFor = "let number of ar" > { { number } } < / li >

Table with ngIf and ngFor

Displays the table only if the array is not null and contains elements

<table border='1' width='100%' *ngIf='books && books.length > 0'> <tbody> <tr *ngFor='let b of books'> <td> {{b.Id}} </td> <td> {{b.Name}} </td> <td> {{b.Price }} </td> <td> {{b.Rate}} </td> </tr> </tbody> </table> 1 2 3 4 5 6 7 8 9 10 < table border = '1' width = '100%' * ngIf = 'books && books.length > 0' > < tbody > < tr * ngFor = 'let b of books' > < td > { { b . Id } } < / td > < td > { { b . Name } } < / td > < td > { { b . Price } } < / td > < td > { { b . Rate } } < / td > < / tr > < / tbody > < / table >

ngStyle

code:

style1 = { 'color': 'green', 'font-size': 20 } 1 2 3 4 style1 = { 'color' : 'green' , 'font-size' : 20 }

Template:

<label [ngStyle]="style1">Bye</label> 1 < label [ ngStyle ] = "style1" > Bye < / label >

ngClass

<label [ngClass]="'s1'">Hi</label> 1 < label [ ngClass ] = "'s1'" > Hi < / label >

In the CSS file (or inline style)

.s1 { color: red; font-size: 30px; } 1 2 3 4 . s1 { color : red ; font - size : 30px ; }

Nested components

Creating a new component:

# ng g c Comp2 1 # ng g c Comp2

using inline style and template:

# ng g c --it --is Comp3 1 # ng g c --it --is Comp3

Creating the new file(s) in the same directory

# ng g c --flat Comp4 1 # ng g c --flat Comp4

Input parameter

In the child component add:

@Input() name:string ; 1 @ Input ( ) name : string ;

bind the variable to a template item

In the parent component declare a child using the child selector and send the value

<app-comp2 [name]="n1"></app-comp2> 1 < app - comp2 [ name ] = "n1" > < / app - comp2 >

Or:

<app-comp2 name="{{n1}}"></app-comp2> 1 < app - comp2 name = "{{n1}}" > < / app - comp2 >

ng-content

You can add any element between the child tags and use it in the child component using <ng-content>

Parent:

<app-comp2 [name]="n1"> <h2>some text</h2> </app-comp2> 1 2 3 < app - comp2 [ name ] = "n1" > < h2 > some text < / h2 > < / app - comp2 >

child:

<p> Child component </p> <ng-content></ng-content> 1 2 3 4 < p > Child component < / p > < ng - content > < / ng - content >

Output parameter (event from child to parent)

Child – Declare output variable

@Output() bclick = new EventEmitter<number>(); 1 @ Output ( ) bclick = new EventEmitter < number > ( ) ;

somewhere in the child code raise the event to the parent:

this.bclick.emit(100); 1 this . bclick . emit ( 100 ) ;

Parent

<app-comp2 (bclick)="bc($event)" > 1 < app - comp2 ( bclick ) = "bc($event)" >

2-way databinding

This syntax

<input type="text" [(ngModel)]="num" /> 1 < input type = "text" [ ( ngModel ) ] = "num" / >

is equal to:

<input type="text" [ngModel]="num" (ngModelChange)="num = $event"/> 1 < input type = "text" [ ngModel ] = "num" ( ngModelChange ) = "num = $event" / >

To make 2 way databinding between the parent and the child declare the following at the child component:

@Output() resultChange = new EventEmitter(); @Input() set result(val) { this.res = val; this.resultChange.emit(val); } get result() { return this.res; } 1 2 3 4 5 6 7 8 9 10 11 @ Output ( ) resultChange = new EventEmitter ( ) ; @ Input ( ) set result ( val ) { this . res = val ; this . resultChange . emit ( val ) ; } get result ( ) { return this . res ; }

Now, in the parent component add:

<comp4 [(result)]="var1"></comp> 1 < comp4 [ ( result ) ] = "var1" > < / comp >

ViewChild

You can declare a child component object in the parent class and access its properties and methods using code for example:

Child

@Component({ selector: 'comp3', template: ` val1:<input type="text" [(ngModel)]="n1"/><br/> val2:<input type="text" [(ngModel)]="n2"/> `, styles: [] }) export class Comp3Component { n1:string = "first"; n2:string = "last"; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @ Component ( { selector : 'comp3' , template : ` val1 : < input type = "text" [ ( ngModel ) ] = "n1" / > < br / > val2 : < input type = "text" [ ( ngModel ) ] = "n2" / > ` , styles : [ ] } ) export class Comp3Component { n1 : string = "first" ; n2 : string = "last" ; }

In the parent class declare:

@ViewChild(Comp3Component) vc:Comp3Component; 1 @ ViewChild ( Comp3Component ) vc : Comp3Component ;

The above decorator attach the object to the first instance of the child component found in the template – if you have only one child, you can access it using code:

console.log(vc.n1 + “:” vc.n2); 1 console . log ( vc . n1 + “ : ” vc . n2 ) ;

ViewChildren

If you have more than one instance of comp3 you can declare it using:

@ViewChildren(Comp3Component) vcs: QueryList<Comp3Component>; 1 @ ViewChildren ( Comp3Component ) vcs : QueryList < Comp3Component > ;

Now declare also