Projecting Content into Components with ng-content in Angular

Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.

Single-slot content projection

server.component.html

<h2>Title</h2>
<p>
  <ng-content></ng-content>
</p>

app.component.html

<app-server>
  <p><i>Hello World</i></p>
</app-server>

Multi-slot content projection

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

@Component({
  selector: 'app-zippy-multislot',
  template: `
    <h2>Multi-slot content projection</h2>

    Default:
    <ng-content></ng-content>

    Question:
    <ng-content select="[question]"></ng-content>
  `
})
export class ZippyMultislotComponent {}
<app-zippy-multislot>
  <p question>
    Is content projection cool?
  </p>
  <p>Let's learn about content projection!</p>
</app-zippy-multislot>

References
https://github.com/mhdr/AngularSamples/tree/master/015/my-app
https://blog.angular-university.io/angular-ng-content/
https://angular.io/guide/content-projection

Getting Access to the Template DOM with @ViewChild in Angular

<div class="col-md-9">
  <input type="text" class="form-control" trim #nickName />
</div>
<div class="row">
  <button class="btn" (click)="onAddGift(nickName)">Add Gift</button>
</div>
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Gift } from '../gift/gift.component';
 
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
  @ViewChild('nickName') nickName : ElementRef;
  userNickName: String = '';
 
  ..
 
  onAddGift(nickName: HTMLInputElement) {
    ..
    this.userNickName = nickName.nativeElement.value;
    ..
  }
  
}

References
http://www.jcombat.com/angular-5/local-references-in-angular

Local References in Angular

Note that we can only access local references in template, not on TypeScript code

<div class="col-md-9">
  <input type="text" class="form-control" trim #giftName />
</div>
<div class="row">
  <button class="btn" (click)="onAddGift(giftName)">Add Gift</button>
</div>
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Gift } from '../gift/gift.component';
 
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
  userNickName: String = '';
 
  ..
 
  onAddGift(giftName: HTMLInputElement) {
    this.userGiftName = giftName.value;
    ..
    ..
  }
  
}

There is another way to do this using @ViewChild decorator.

References
http://www.jcombat.com/angular-5/local-references-in-angular

How to disable View (css) Encapsulation in Angular

A component’s styles can be encapsulated within the component’s host element so that they don’t affect the rest of the application.

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

@Component({
  moduleId: module.id,
  selector: 'my-zippy',
  templateUrl: 'my-zippy.component.html',
  styles: [`
    .zippy {
      background: green;
    }
  `],
  encapsulation: ViewEncapsulation.None
})
class ZippyComponent {
  @Input() title: string;
}

References
https://angular.io/api/core/ViewEncapsulation
https://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html

Binding to Custom Events of Component in Angular

server.component.ts

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

@Component({
  selector: 'app-server',
  templateUrl: './server.component.html',
  styleUrls: ['./server.component.css']
})
export class ServerComponent implements OnInit {

  // this is now an event
  @Output() statusChanged = new EventEmitter<{ serverId: number, time: Date }>();
  status = 'offline';

  constructor() {
    setTimeout(() => {
      this.status = 'online';

      // fire event
      this.statusChanged.emit({serverId: 10, time: new Date()});
    }, 5000);
  }

  ngOnInit() {
  }

}

server.component.html

<p>
  server is {{status}}
</p>

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  serverId;
  time;

  /**
   * receive data from event
   */
  onServerStatusChanged(data: { serverId: number, time: Date }) {
    this.serverId = data.serverId;
    this.time = data.time;
  }
}

app.component.html

<app-server (statusChanged)="onServerStatusChanged($event)"></app-server>
<p>Server Id : {{serverId}}, Date : {{time}}</p>

Assigning an Alias to Custom Events

@Output('nicolas') nic  = new EventEmitter<any>();

References
https://github.com/mhdr/AngularSamples/tree/master/013/my-app

Binding to Custom Properties of Components in Angular

server.component.ts

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

@Component({
  selector: 'app-server',
  templateUrl: './server.component.html',
  styleUrls: ['./server.component.css']
})
export class ServerComponent implements OnInit {

  // Now this is a property for component
  @Input() firstName: string;

  constructor() {
  }

  ngOnInit() {
  }

}

server.component.html

<p>
  Hello {{firstName}}
</p>

app.component.html

<app-server [firstName]="'Mahmood'"></app-server>
<app-server [firstName]="'Mehdi'"></app-server>

Assigning an Alias to Custom Properties

@Input('selectedHero') hero: string;

References
https://github.com/mhdr/AngularSamples/tree/master/012/my-app

Outputting Lists with ngFor on Angular

server.component.html

<p>
  server {{serverId}} is {{status}}
</p>

server.component.ts

import {Component, OnInit} from '@angular/core';
import {el} from '@angular/platform-browser/testing/src/browser_util';

@Component({
  selector: 'app-server',
  templateUrl: './server.component.html',
  styleUrls: ['./server.component.css']
})
export class ServerComponent implements OnInit {

  serverId = 0;
  status = 'offline';

  constructor() {

    // choose a number between 0 and 100
    this.serverId = Math.floor((Math.random() * 100) + 1);

    const random2 = Math.random();

    if (random2 > 0.5) {
      this.status = 'online';
    } else {
      this.status = 'offline';
    }

  }

  ngOnInit() {
  }

}

app.component.html

<input type="button" value="Add Server" (click)="onButtonClick()"/>
<app-server *ngFor="let s of servers"></app-server>

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  servers = [];

  onButtonClick() {
    // just push a date to servers
    this.servers.push(new Date());
  }
}

Getting the Index when using ngFor

<app-server *ngFor="let s of servers;let i=index" [ngClass]="{'even':i%2==0}"></app-server>

References
https://github.com/mhdr/AngularSamples/tree/master/011/my-app

Applying CSS Classes Dynamically with ngClass on Angular

app.component.html

<input type="button" value="Start" (click)="onButtonClick()"/>
<div [ngClass]="{name:isClicked}">Hello World 4</div>

app.component.css

.name {
  background-color: aquamarine;
}

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  isClicked = false;

  onButtonClick() {
    this.isClicked = true;
  }
}

Method 2

<div [class.extra-sparkle]="isDelightful">	

Binds the presence of the CSS class extra-sparkle on the element to the truthiness of the expression isDelightful.

References
https://github.com/mhdr/AngularSamples/tree/master/010/my-app

Styling Elements Dynamically with ngStyle on Angular

app.component.html

<div [ngStyle]="{backgroundColor:'Red'}">Hello World</div>
<div [ngStyle]="{backgroundColor:backgroundColor}">Hello World 2</div>
<div [ngStyle]="{backgroundColor:getBackgroundColor()}">Hello World 3</div>

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  backgroundColor = 'Blue';

  getBackgroundColor() {
    return 'Green';
  }
}

References
https://github.com/mhdr/AngularSamples/tree/master/010/my-app