Angular components 2

May 2017, Nejc Zdovc

workshop #8

AGENDA

    Projection
    Encapsulation
    Two-Way binding
   Events, Host binding
    pipes (usage)
    ngSwitch
    ngClass
    ngStyle

Projection

Single-slot content

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <div class="my-component">
      <ng-content></ng-content>
    </div>
  `
})
export class MyComponent {}

my-component.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <div class="app">
      <my-component>
        This is my transcluded content!
      </my-component>
    </div>
  `
})
export class AppComponent {}

app.component.ts

MULTI-slot content

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <div class="my-component">
      <div>
        Title:
        <ng-content 
            select=".my-component-title">
        </ng-content>
      </div>
      <div>
        Content:
        <ng-content
            select=".my-component-content">
        </ng-content>
      </div>
    </div>
  `
})
export class MyComponent {}

my-component.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <div class="app">
      <my-component>
        <div class="my-component-title">
          This is the Component title!
        </div>
        <div class="my-component-content">
          And here's some awesome content.
        </div>
      </my-component>
    </div>
  `
})
export class AppComponent {}

app.component.ts

Encapsulation

NONE

<!DOCTYPE html>
<html>
  <head>
    <style>
      p { 
        color: red;
      }
    </style>
  </head>
  <body>
    <my-component>
        <p>This is title</p>
    </my-component>
  </body>
</html>

generated index.html

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>
        This is title
    </p>
  `,
  styles: [`
    p {
      color: red;
    }
  `],
  encapsulation: ViewEncapsulation.None
})
export class MyComponent {}

my-component.component.ts

Emulated - Default

<!DOCTYPE html>
<html>
  <head>
    <style>
      p[_ngcontent-0] { 
        color: red;
      }
    </style>
  </head>
  <body>
    <my-component _ngcontent-0>
        <p _ngcontent-0>This is title</p>
    </my-component>
  </body>
</html>

generated index.html

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>
        This is title
    </p>
  `,
  styles: [`
    p {
      color: red;
    }
  `],
  encapsulation: ViewEncapsulation.Emulated
})
export class MyComponent {}

my-component.component.ts

NATIVE

<!DOCTYPE html>
<html>
  <body>
    <my-component>
       #shadow-root
       | <style>
       |   p { 
       |     color: red;
       |   }
       | </style>
       | <p>This is title</p>
    </my-component>
  </body>
</html>

generated index.html

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>
        This is title
    </p>
  `,
  styles: [`
    p {
      color: red;
    }
  `],
  encapsulation: ViewEncapsulation.Native
})
export class MyComponent {}

my-component.component.ts

Two-Way binding

LONG VERSION

<input [ngModel]="username" (ngModelChange)="username = $event">

<p>Hello {{username}}!</p>

hello.component.html

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: 'hello.component.html'
})
export class HelloComponent {
    username = 'Angular';
}

hello.component.ts

<input [value]="username" (input)="username = $event.target.value">

<p>Hello {{username}}!</p>

SHORT VERSION

<input [(ngModel)]="username">

<p>Hello {{username}}!</p>

hello.component.html

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: 'hello.component.html'
})
export class HelloComponent {
    username = 'Angular';
}

hello.component.ts

Host binding /

HOST LISTENER

HOST LISTENER

import {Component, HostListener} from '@angular/core';

@Component({
    selector: 'hello-component',
    templateUrl: './hello.component.html',
    styleUrls: ['./hello.component.css']
})
export class HelloComponent {
    @HostListener('mouseenter') onMouseEnter() {
        console.log('mouse entered hello component');
    }

    @HostListener('mouseleave', ['$event']) onMouseLeave(e) {
        console.log('mouse left component', e);
    }
}

hello.component.ts

HOST BINDING

import {Component, HostBinding} from '@angular/core';

@Component({
    selector: 'hello-component',
    templateUrl: './hello.component.html',
    styleUrls: ['./hello.component.css']
})
export class HelloComponent {
    @HostBinding('class.valid') isValid = false;

    onClick() {
        this.isValid = true;
    }
}

hello.component.ts

<button (click)="onClick()">Validate</button>

hello.component.html

PIPES

UPPERCASE

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>
        {{ title | uppercase }}
    </p>
  `,
})
export class MyComponent {
    title = 'This is title'
}

my-component.component.ts

THIS IS TITLE

output

LOWERCASE

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>
        {{ title | lowercase }}
    </p>
  `,
})
export class MyComponent {
    title = 'This is title'
}

my-component.component.ts

this is title

output

DATE

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>
        {{ birthday | date:"dd. MM. yyyy" }}
    </p>
    <p>
        {{ birthday | date:"fullDate" | uppercase }}
    </p>
  `,
})
export class MyComponent {
    birthday = new Date(1988, 3, 15); // April 15, 1988
}

my-component.component.ts

15. 04. 1988
FRIDAY, APRIL 15, 1988

output

NUMBER

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
   <p>e (no formatting): {{e}}</p>
    <p>e (3.1-5): {{e | number:'3.1-5'}}</p>
    <p>pi (no formatting): {{pi}}</p>
    <p>pi (3.5-5): {{pi | number:'3.5-5'}}</p>
  `,
})
export class MyComponent {
  pi: number = 3.141592;
  e: number = 2.718281828459045;
}

my-component.component.ts

e (no formatting): 2.718281828459045
e (3.1-5): 002.71828
pi (no formatting): 3.141592
pi (3.5-5): 003.14159

output

CURRENCY

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>A: {{a | currency:'USD':false}}</p>
    <p>B: {{b | currency:'USD':true:'4.2-2'}}</p>
  `,
})
export class MyComponent {
    a: number = 0.259;
    b: number = 1.3495;
}

my-component.component.ts

A: USD0.26
B: $0,001.35

output

PERCENT

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
  template: `
    <p>A: {{a | percent}}</p>
    <p>B: {{b | percent:'4.3-5'}}</p>
  `,
})
export class MyComponent {
    a: number = 0.259;
    b: number = 1.3495;
}

my-component.component.ts

A: 25.9%
B: 0,134.950%

output

ng*

ngswitch

<div [ngSwitch]="carType">
  <span *ngSwitchCase="family">Welcome family guy</span>
  <span *ngSwitchCase="sport">Wruum Wruuum</span>
  <span *ngSwitchCase="off-roaders">Hi you on the hill</span>
  <span *ngSwitchCase="luxury">Blink Blink</span>
  <p *ngSwitchDefault>Motorcycle is fine as well</p>
</div>

hello.component.html

import {Component, OnInit} from '@angular/core';

@Component({
    selector: 'hello',
    templateUrl: './hello.component.html',
    styleUrls: ['./hello.component.css']
})
export class HelloComponent implements OnInit {
    carType: string = 'family' | 'sport' | 'off-roaders' | 'luxury';

    ngOnInit() {
        this.carType = 'sport';
    }
}

hello.component.ts

NGCLASS

<div [ngClass]="{'first': isFirst, 'second': !isFirst, 'third': true}">
    Who is it?
</div>

<button (click)="onClick()">Toggle first</button>

hello.component.html

import {Component, OnInit} from '@angular/core';

@Component({
    selector: 'hello',
    templateUrl: './hello.component.html',
    styleUrls: ['./hello.component.css']
})
export class HelloComponent implements OnInit {
    isFirst: boolean = true;

    onClick() {
        this.isFirst = !this.isFirst;
    }
}

hello.component.ts

NGSTYLE

<div [ngStyle]="{
    'color': getRandomColor(),
    'font-size: '16px'
}">
    RAINBOW
</div>

hello.component.html

import {Component, OnInit} from '@angular/core';

@Component({
    selector: 'hello',
    templateUrl: './hello.component.html',
    styleUrls: ['./hello.component.css']
})
export class HelloComponent implements OnInit {
    getRandomColor(){
        const chars: string[] = '0123456789ABCDEF'.split('');
        let color = '#';
        for (let i = 0; i < 6; i++){
            color += chars[Math.floor(Math.random() * 16)];
        }
        return color;
    }
}

hello.component.ts

THANK YOU

Made with Slides.com