import {Component} from 'angular2/core';
@Component({
selector: 'my-app',
template: '<h1>{{ title }}</h1>'
})
export class AppComponent {
title = 'Hello World!';
}
That’s it! That’s all you really need to have a component. Three things are happening here:
That’s a good start, but let’s get into a more complex example that showcases other powerful features of Angular and Typescript/ES2015. In the following example, I've decided to stuff everything into one component. However, if you'd like to stick to best practices and divide the code into different components and services or if you get lost at any point, you can check out the finished/refactored example here. Without any further ado, let’s make a quick page that displays a list of products. Let’s start with the index:
<html>
<head>
<title>Products</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<link rel="stylesheet" href="styles.css">
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/main')
.then(null, console.error.bind(console));
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
There’s nothing out of the ordinary going on here. You are just importing all of the necessary scripts for your application to work as demonstrated in the quick-start.
The app/main.ts file should already look somewhat similar to this:
import {bootstrap} from ‘angular2/platform/browser’
import {AppComponent} from ‘./app.component’
bootstrap(AppComponent);
Here, we imported the bootstrap function from the Angular 2 package and an AppComponent class from the local directory. Then, we initialized the application.
First, create a product class that defines the constructor and type definition of any products made. Then, create app/product.ts, as follows:
export class Product {
id: number;
price: number;
name: string;
}
Next, you will create an app.component.ts file, which is where the magic happens. I've decided to stuff everything in here for demonstration purposes, but ideally, you would want to extract the products array into its own service, the HTML template into its own file, and the product details into its own component. This is how the component will look:
import {Component} from 'angular2/core';
import {Product} from './product'
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
<ul class="products">
<li *ngFor="#product of products"
[class.selected]="product === selectedProduct"
(click)="onSelect(product)">
<span class="badge">{{product.id}}</span> {{product.name}}
</li>
</ul>
<div *ngIf="selectedProduct">
<h2>{{selectedProduct.name}} details!</h2>
<div><label>id: </label>{{selectedProduct.id}}</div>
<div><label>Price: </label>{{selectedProduct.price | currency: 'USD': true }}</div>
<div>
<label>name: </label>
<input [(ngModel)]="selectedProduct.name" placeholder="name"/>
</div>
</div>
`,
styleUrls: ['app/app.component.css']
})
export class AppComponent {
title = 'My Products';
products = PRODUCTS;
selectedProduct: Product;
onSelect(product: Product) { this.selectedProduct = product; }
}
const PRODUCTS: Product[] = [
{ "id": 1, "price": 45.12, "name": "TV Stand" },
{ "id": 2, "price": 25.12, "name": "BBQ Grill" },
{ "id": 3, "price": 43.12, "name": "Magic Carpet" },
{ "id": 4, "price": 12.12, "name": "Instant liquidifier" },
{ "id": 5, "price": 9.12, "name": "Box of puppies" },
{ "id": 6, "price": 7.34, "name": "Laptop Desk" },
{ "id": 7, "price": 5.34, "name": "Water Heater" },
{ "id": 8, "price": 4.34, "name": "Smart Microwave" },
{ "id": 9, "price": 93.34, "name": "Circus Elephant" },
{ "id": 10, "price": 87.34, "name": "Tinted Window" }
];
The app/app.component.css file will look something similar to this:
.selected {
background-color: #CFD8DC !important;
color: white;
}
.products {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 15em;
}
.products li {
position: relative;
min-height: 2em;
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
border-radius: 4px;
font-size: 16px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: #3F51B5;
display: block;
width: 100%;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
-ms-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.products li.selected:hover {
background-color: #BBD8DC !important;
color: white;
}
.products li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
color: #3F51B5;
text-decoration: none;
font-size: 1.2em;
background-color: rgba(0,0,0,0.01);
}
.products .text {
position: relative;
top: -3px;
}
.products .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: 0;
height: 2em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
I'll explain what is happening:
Also worth noting are the following:
That's it! You now have a bit more complex component that has a particular functionality. As I previously mentioned, this could be refactored, and that would look something similar to this:
import {Component, OnInit} from 'angular2/core';
import {Product} from './product';
import {ProductDetailComponent} from './product-detail.component';
import {ProductService} from './product.service';
@Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
styleUrls: ['app/app.component.css'],
directives: [ProductDetailComponent],
providers: [ProductService]
})
export class AppComponent implements OnInit {
title = 'Products';
products: Product[];
selectedProduct: Product;
constructor(private _productService: ProductService) { }
getProducts() {
this._productService.getProducts().then(products => this.products = products);
}
ngOnInit() {
this.getProducts();
}
onSelect(product: Product) { this.selectedProduct = product; }
}
In this example, you get your product data from a service and separate the product detail template into a child component, which is much more modular. I hope you've enjoyed reading this post.
David Meza is an AngularJS developer at the City of Raleigh. He is passionate about software engineering and learning new programming languages and frameworks. He is most familiar working with Ruby, Rails, and PostgreSQL in the backend and HTML5, CSS3, JavaScript, and AngularJS in the frontend. He can be found at here.