Angular
Component
Component basically consists of logic, template (UI) and style
import { Component } from '@angular/core';
@Component({
selector: 'app-component-overview',
templateUrl: './component-overview.component.html',
styleUrls: ['./component-overview.component.css']
})
export class ComponentOverviewComponent {
}
Life Cycle
ngOnChange (Trigger when state is changed) -> ngOnInit -> ngDoCheck -> ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit -> ngAfterViewChecked -> ngOnDestroy
View Encapsulation
To encapsulate to the component to separate the css
Emulated (generated css class name with uniqueness)
None
Get Props from parent
import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
selector: 'app-hero-child',
template: `
<h3>{{hero.name}} says:</h3>
<p>I, {{hero.name}}, am at your service, {{masterName}}.</p>
`
})
export class HeroChildComponent {
@Input() hero!: Hero;
@Input('master') masterName = '';
}
Child emit event to the parent
import { Component } from '@angular/core';
@Component({
selector: 'app-vote-taker',
template: `
<h2>Should mankind colonize the Universe?</h2>
<h3>Agree: {{agreed}}, Disagree: {{disagreed}}</h3>
<app-voter
*ngFor="let voter of voters"
[name]="voter"
(voted)="onVoted($event)">
</app-voter>
`
})
export class VoteTakerComponent {
agreed = 0;
disagreed = 0;
voters = ['Dr. IQ', 'Celeritas', 'Bombasto'];
onVoted(agreed: boolean) {
if (agreed) {
this.agreed++;
} else {
this.disagreed++;
}
}
}
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-voter',
template: `
<h4>{{name}}</h4>
<button type="button" (click)="vote(true)" [disabled]="didVote">Agree</button>
<button type="button" (click)="vote(false)" [disabled]="didVote">Disagree</button>
`
})
export class VoterComponent {
@Input() name = '';
@Output() voted = new EventEmitter<boolean>();
didVote = false;
vote(agreed: boolean) {
this.voted.emit(agreed);
this.didVote = true;
}
}
import { AfterViewInit, ViewChild } from '@angular/core';
import { Component } from '@angular/core';
import { CountdownTimerComponent } from './countdown-timer.component';
@Component({
selector: 'app-countdown-parent-vc',
template: `
<h3>Countdown to Liftoff (via ViewChild)</h3>
<button type="button" (click)="start()">Start</button>
<button type="button" (click)="stop()">Stop</button>
<div class="seconds">{{ seconds() }}</div>
<app-countdown-timer></app-countdown-timer>
`,
styleUrls: ['../assets/demo.css']
})
export class CountdownViewChildParentComponent implements AfterViewInit {
@ViewChild(CountdownTimerComponent)
private timerComponent!: CountdownTimerComponent;
seconds() { return 0; }
ngAfterViewInit() {
// Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
// but wait a tick first to avoid one-time devMode
// unidirectional-data-flow-violation error
setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
}
start() { this.timerComponent.start(); }
stop() { this.timerComponent.stop(); }
}
Content Projection
import { Component } from '@angular/core';
@Component({
selector: 'app-zippy-basic',
template: `
<h2>Single-slot content projection</h2>
<ng-content></ng-content>
`
})
export class ZippyBasicComponent {}
<app-zippy-basic>
<p>Is content projection cool?</p>
</app-zippy-basic>
Pipe
Pipes are simple functions to use in template expressions to accept an input value and return a transformed value.
The built-in pipes include date, upper case, lower case, etc
<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>
Directive
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) {
this.el.nativeElement.style.backgroundColor = 'yellow';
}
}
<p appHighlight>Highlight me!</p>
Dependency Injection
import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes';
@Injectable({
// declares that this service should be created
// by the root application injector.
providedIn: 'root',
})
export class HeroService {
getHeroes() { return HEROES; }
}
Inject by constructor on component
@Component({ … })
class HeroListComponent {
constructor(private service: HeroService) {}
}
Re rendering
Angular uses a different approach called "change detection, with help of zonejs Angular tracks changes in the component's state and bindings by comparing the current and previous values of the bindings. When changes are detected, Angular updates the corresponding parts of the actual DOM by using renderer 2
Angular walks your components from top to bottom, looking for changes. Angular runs its change detection mechanism periodically so that changes to the data model are reflected in an application’s view
Change Detection Initiation: Angular triggers the change detection process, either explicitly or automatically based on certain events (such as user interactions or asynchronous operations).
Component Tree Traversal: Angular traverses the component tree, starting from the root component, and checks each component for changes. This traversal can be considered a top-down approach.
Change Detection and Update: For each component, Angular compares the current state and bindings with their previous values to detect changes. If changes are detected, Angular updates the component's views and the associated DOM elements.
DOM Update: After detecting changes and updating the component's views, Angular applies the necessary changes to the DOM to reflect the updated state.
Last updated
Was this helpful?