Angular 2 architecture quickstart: components, inputs, and services

Yitz Schaffer
Feb 23, 2017 · 2 min read

This is a guide for developers with experience creating applications in other frameworks, who are new to Angular 2 and trying to get a sense of its architectural patterns. We’re going to focus on components and how they communicate with the rest of the application. There are other ways of doing these things; this is my opinion of the best ones given my current understanding.

Components

These are the building blocks of an application: self-contained systems typically including a controller (the component’s class) and a view specified by a template.

A component is typically included by other parent components by referencing its selector in the parent template.

@Component({
selector: 'product'
})
<!-- inside some other component's template: -->
<product></product>

Two-way binding is provided by Angular for public properties of the controller.

export class ProductComponent {
public name: string;
}
<!--
when the input's value changes, the component's name property is updated, and vice versa, via 2-way binding
-->
<input ([ngModel])="name" />

Inputs and Outputs

These are one way in which components communicate with each other. Because inputs and outputs couple components explicitly, they are best used when a child component would never exist outside this particular context — composition rather than aggregation, in classical OOP terms.

Inputs are exposed as component properties, and also as a stream of change events.

export class ProductComponent implements OnChanges {
@Input isFeatured: boolean;

ngOnChanges(changes: SimpleChanges) {
// receives a stream of changes to any inputs, e.g. when
// localValueOfFeatured changes in the parent (see below)
}
}
<product [isFeatured]="localValueOfFeatured"></product>

Outputs are exposed to the parent via an event stream.

@Component({
template: `<button (click)="like()">Like</button>`
})
export class ProductComponent {
@Output onLike = new EventEmitter<boolean>();

like() {
this.onLike.emit(true);
}
}
<product (onLike)="handleLikesInParentComponent($event)"></product>

Services

This is the other way to move data in and out of components. More generally though, services are modular objects injectable magically by Angular on demand. They can communicate with other services injected into them, as well as publishing their own data streams. Perhaps the most common example is the Http service, which allows us to make an outgoing web services request.

In the context of inter-component communication, services are the better choice over inputs and outputs when the source or destination of a data stream is nonessential to the component. Each component depends on the service responsible for this line of communication, rather than on each other.

@Component({
template: `<button (click)="like()">Like</button>`
})
export class ProductComponent {
private product: Product; // a model object

// request injection of the service
constructor (private productLikeService: ProductLikeService) {}

like() {
this.productLikeService.publish(this.product);
}
}
export class ProductLikeService {
this.subject = new Subject<Product>();

subscribe() {
return this.subject.asObservable();
}

publish(product: Product) {
// any consumers of this service will receive the product
this.subject.next(product);
}
}

Yitz Schaffer
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade