1. Components
An Angular application is a tree of components. A component controls a patch of the screen that we can call a view, and declares reusable UI building blocks for an application. Conceptualize an Angular application design as a tree of nested components, each with its own isolated scope.
We define the application logic inside the component class. We attach the @Component JavaScript decorator function to this, which adds metadata.
selector: tag where to insert and instance of the component.
template: HTML to be rendered in the DOM.
styles: CSS styles for this component.
import { Component } from '@angular/core';
@Component({
selector: 'app-angular',
template: `
<h2>Hello, {{ name }}</h2>
`
})
export class AngularComponent {
name: string;
constructor() {
this.name = 'Angular 4';
}
}
Import Component decorator from @angular/core. Add <app-angular></app-angular> tag to any HTML file or template and Angular will insert an instance of the AngularComponent view in between those tags.
We can pass data into a component with property binding and event binding. @Input() decorator to pass data from parent to child. @Output() decorator to pass data from child to parent. A shared service to publish and subscribe to data and events between sibling components.
Child Component, receive data with @Input():
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-angular',
template: `
<h2>Hello, {{ name }}</h2>
`
})
export class AngularComponent {
@Input() name: string;
}
Parent Component:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="row">
<h1>{{ title }}</h1>
<div class="col-md-6">
<app-angular [name]="name"></app-angular>
</div>
<div class="col-md-6">
<img [src]="imageUrl" style="height:70rem;">
</div>
</div>
`
})
export class AppComponent {
title = 'Angular Exploration';
imageUrl = '../assets/keras10.jpg';
name = 'Angular 4';
}
Click event handler with @Ouput(), send data out of component:
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<div>
<p>Count: {{ count }}</p>
<button class="btn btn-danger" (click)="changer(1)">Increment</button>
<button class="btn btn-warning" (click)="changer(0)">Decrement</button>
</div>
`
})
export class CounterComponent {
@Input() count: number;
@Output() result = new EventEmitter<number>();
changer(type: number) {
this.count = type ? this.count += 1 : this.count -= 1;
this.result.emit(this.count);
}
}
The component defines a public API with its input and output bindings. Square brackets to pass inputs and parenthesis to handle outputs:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="row">
<h1>{{ title }}</h1>
<div class="col-md-6">
<app-counter [count]="iCount" (result)=changed($event)></app-counter>
</div>
<div class="col-md-6">
<img [src]="imageUrl" style="height:70rem;">
</div>
</div>
`
})
export class AppComponent {
title = 'Angular Exploration';
imageUrl = '../assets/keras10.jpg';
iCount = 0;
changed(value: number) {
this.iCount = value;
}
}
Template reference variable preceded with a hash or pound symbol:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="row">
<h1>{{ title }}</h1>
<div class="col-md-6">
<section>
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
<label for="name">Name</label>
<input type="text" name="name" id="name" ngModel>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Form Value: {{ formValue }}
</section>
</div>
<div class="col-md-6">
<img [src]="imageUrl" style="height:70rem;">
</div>
</div>
`
})
export class AppComponent {
title = 'Angular Exploration';
imageUrl = '../assets/keras10.jpg';
formValue: Object;
onSubmit(myForm) {
this.formValue = JSON.stringify(myForm.value);
}
}
Accessing component properties from the template. Child component:
import { Component } from '@angular/core';
@Component({
selector: 'app-profile',
template: ``
})
export class ProfileComponent {
name = 'Nils-Holger Nägele';
age = 46;
gender = 'male';
status = 'single';
location = 'Frankfurt, Germany';
profession = 'Software Engineer';
driver = 'Code with Passion ...';
}
AppComponent with template reference variable in component:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="row">
<h1>{{ title }}</h1>
<div class="col-md-6">
<app-profile #profile></app-profile>
My name is {{ profile.name }}.
My job is {{ profile.profession }}.
</div>
<div class="col-md-6">
<img [src]="imageUrl" style="height:70rem;">
</div>
</div>
`
})
export class AppComponent {
title = 'Angular Exploration';
imageUrl = '../assets/keras10.jpg';
}
Projection or transclusion with <ng-content>:
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<div style="border: 2px solid red; padding: 2rem;">
<h4>My Child Component</h4>
<ng-content></ng-content>
</div>
`
})
export class ChildComponent { }
Child component tag in the template, any markup that appears between opening and closing tags of <app-child>, place inside of <ng-content></ng-content>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="row">
<h1>{{ title }}</h1>
<div class="col-md-6">
<app-child>
<p>je l'aime <i>a fonds</i> ma princesse polymer, ma belle.</p>
</app-child>
</div>
<div class="col-md-6">
<img [src]="imageUrl" style="height:70rem;">
</div>
</div>
`
})
export class AppComponent {
title = 'Angular Exploration';
imageUrl = '../assets/keras10.jpg';
}
Multiple ng-content tags and specify position of projected content to certain ng-content like this:
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<div style="border: 2px solid red; padding: 2rem;">
<h4>My Child Component with Select</h4>
<div class="alert alert-danger">
<ng-content select="header"></ng-content>
</div>
<div class="alert alert-info">
<ng-content select="section"></ng-content>
</div>
<div class="alert alert-success">
<ng-content select="footer"></ng-content>
</div>
</div>
`
})
export class ChildComponent { }
In template use directives to specify content of directives:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="row">
<h1>{{ title }}</h1>
<div class="col-md-6">
<app-child>
<footer>Footer</footer>
<section>Section</section>
<header>Header</header>
</app-child>
</div>
<div class="col-md-6">
<img [src]="imageUrl" style="height:70rem;">
</div>
</div>
`
})
export class AppComponent {
title = 'Angular Exploration';
imageUrl = '../assets/keras10.jpg';
}
Separation of Components
Divide responsibility of components in:
- Smart/Container components are components with access to the application's domain model.
- Dumb/Presentational components are components responsible for UI rendering.
Group Components in a Module
Group related components in a feature model, see NgModule.