Dimitry Karpenko
Java/Eclipse developer in MyEclipse and Webclipse teams.
Java/Eclipse developer in MyEclipse and Webclipse teams.
Angular 2 is a framework for building desktop and mobile web applications. After hearing rave reviews about Angular 2, I decided to check it out and take my first steps into modern web development. In this article, I’ll show you how to create a simple master-details application using Angular 2, TypeScript, Angular CLI and Eclipse Java EE.
Looking for a commercial solution? Give Webclipse a try.
Let’s create a simple app containing a vehicle list with the ability to edit vehicle properties. I’ve included a sample project that you can refer to.
Create the project using the New Dynamic Web Project wizard in Eclipse. To access this wizard, select File>New>Dynamic Web Project; or right click in Project/Package Explorer and choose New>Dynamic Web Project; or select New>Other… and select Dynamic Web Project from the list of available wizards.
Type Vehicles for the project name and click Finish—that’s all you need here.
Angular CLI is a command-line tool that allows you to create a working Angular 2 application out-of-the-box without a massive amount of manual work—and also allows you to generate Angular 2 components, services, etc. in the same way. Let’s try it! Right-click the newly created project and select Show in>Terminal.
From the Terminal view, type ng init
. After the process finishes, refresh the project in Eclipse—the src folder is updated with an app folder and several files; index.html (well-known to web developers) and main.ts among them. Is this really all that’s required to get an Angular 2 Hello World application? Yes! Open the project in Terminal view and type npm start
. After a short time, you’ll see output like:
Serving on http://localhost:4200/
Build successful - 17270ms.
Open your browser (I use Chrome for testing) and type the given URL (http://localhost:4200/). You’ll see a “Loading…” message and then “App works!”. See, it actually works!
Let’s go ahead and create a model for our app. This model will be pretty simple. Create a package app.model in your src folder, and in it create file vehicle.ts with the following contents:
export class Vehicle {
id;
name;
type;
mass;
}
The class contains only four fields describing some vehicle.
It’s time to make some UI bricks for our application, called components. Open the Terminal view for folder (Your Project)>Java Resources>src>app and type ng g component vehicle-list
. The CLI command ng with the key g (or generate) is responsible for generating Angular 2 application entities and, particularly, components.
As you can conclude from its name, vehicle-list is responsible for displaying a list with vehicle details. Let’s expand vehicle-list folder and open vehicles-list.component.ts:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-vehicles-list',
templateUrl: 'vehicles-list.component.html',
styleUrls: ['vehicles-list.component.css']
})
export class VehiclesListComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
All the basic component infrastructure is present here.
OK, we’ll definitely need to store a list of our vehicles somewhere. Let’s add field vehicles: Vehicle[];
to the VehiclesListComponent
class. Of course, Vehicle will be highlighted in red—currently, the TS compiler knows nothing about it. To fix this, add import { Vehicle } from '../model/vehicle';
to the imports section and save the file. The red highlighting should disappear. If not, make a small edit (like adding space) and save again—unfortunately, the current version of the TypeScript plugin has poor validation.
Well, now we have a vehicle list, but how can we interact with it? Passing it to the constructor would make our code less flexible by requiring a concrete list to be specified when creating a vehicle list component. There’s a better solution—Angular 2 supports Dependency Injection out-of-the-box, and it can be accomplished using Angular 2 Services.
Go to app.model in the terminal and type ng g service vehicle
. After the command executes, refresh app.model. Two files will be created, vehicle.service.spec.ts and vehicle.service.ts. The last one is interesting to us. For now we won’t implement any complex logic to obtain the list and will just hard code our vehicles list. In the following code we import the Injectable decorator, set up our list, assign given list to class field and return it by demand:
import { Injectable } from '@angular/core';
let vehicles = [
{
id: 1,
name: 'Trailer - 1',
type: 'Truck',
mass: 40
},
{
id: 2,
name: 'An-2',
type: 'Plane',
mass: 5
},
{
id: 3,
name: 'LandCruiser 80',
type: 'Jeep',
mass: 2
},
];
@Injectable()
export class VehicleService {
private vehicles;
constructor() {
this.vehicles = vehicles;
}
getVehicles() {
return this.vehicles;
}
}
Now go back to vehicles-list.component.ts, import VehicleService in the same way as Vehicle is imported, and make 2 more edits: add providers: [VehicleService]
to @Component
and change constructor to:
constructor(private vehicleService: VehicleService) {
this.vehicles = this.vehicleService.getVehicles();
}
We’re basically done with the component, let’s switch to UI. Open vehicle-list.component.html and replace its mock contents with our table.
<table class="tftable">
<tr><th>ID</th><th>Name</th><th>Type</th><th>Mass</th>
<tr *ngFor="let vehicle of vehicles">
<td>{{vehicle.id}}</td> <td>{{vehicle.name}}</td> <td>{{vehicle.type}}</td> <td>{{vehicle.mass}}</td>
</tr>
</table>
We do a conceptually simple thing here—create a table with a constant header and then iterate over vehicles list, creating a table row for each vehicle. A row is composed of cells with corresponding properties.
Also, we specify table class here because we want to have some styling for it—corresponding styles are put into vehicles-list.component.css. You can download the sample project and open them if necessary.
Ok, we’re done with our initial UI. To see the result, just add our selector tag to app.component.html: <app-vehicles-list></app-vehicles-list>
In the Terminal, go to the project root dir and type npm start
…Here we go!
Our table is pretty, but not very interactive, huh? OK, let’s make it a bit more “dynamic” by adding a Details view that displays a clicked table row and allows the fields to be edited. Let’s create VehicleDetailsComponent
under the same parent with VehiclesListComponent
using command ng g component vehicle-details
.
Like it was for Vehicles List, a folder with ts and html/css files will be created. We’ll need to modify 2 of them. VehicleDetailsComponent in vehicle-details.component.ts needs to have a field for current vehicle—vehicle:Vehicle, with @Input directive above. This decorator declares the vehicle field as an input, which makes passing an actual value to it much easier.
Now let’s take a closer look at the template file for it:
<div *ngIf="vehicle">
<h2>{{vehicle.name}} properties</h2>
<table>
<tr>
<td><label>ID: </label></td>
<td>{{vehicle.id}}</td>
</tr>
<tr>
<td><label>Name: </label></td>
<td><input [(ngModel)]="vehicle.name" placeholder="name" /></td>
</tr>
<tr>
<td><label>Type: </label></td>
<td><input [(ngModel)]="vehicle.type" placeholder="type" /></td>
</tr>
<tr>
<td><label>Mass: </label></td>
<td><input [(ngModel)]="vehicle.mass" placeholder="mass" /></td>
</tr>
</table>
</div>
Now, we need to change our VehiclesListComponent
to handle selection. Let’s add a selectedVehicle
field and a method onSelect
to handle selection.
Also, in the html template we’ll need to add a tag for the details component. To make it work, we need to import VehicleDetailsComponent
and add the corresponding directive. After given changes, vehicles-list.component.ts will look like the following:
import { Component, OnInit } from '@angular/core';
import { VehicleService } from '../model/vehicle.service';
import { Vehicle } from '../model/vehicle';
@Component({
selector: 'app-vehicles-list',
templateUrl: 'vehicles-list.component.html',
styleUrls: ['vehicles-list.component.css'],
providers: [VehicleService]
})
export class VehiclesListComponent implements OnInit {
vehicles: Vehicle[];
selectedVehicle: Vehicle;
constructor(private vehicleService: VehicleService) {
this.vehicles = this.vehicleService.getVehicles();
}
ngOnInit() {
}
onSelect(vehicle: Vehicle) { this.selectedVehicle = vehicle; }
}
Next, let’s change the vehicles list template, vehicles-list.component.html. We need to add the click handler to each table row to call the corresponding selection method—(click)="onSelect(vehicle)"
. Also, let’s add a tag for the vehicle details component below our table:
<table class="tftable">
<tr><th>ID</th><th>Name</th><th>Type</th><th>Mass</th>
<tr *ngFor="let vehicle of vehicles"
(click)="onSelect(vehicle)">
<td>{{vehicle.id}}</td> <td>{{vehicle.name}}</td> <td>{{vehicle.type}}</td> <td>{{vehicle.mass}}</td>
</tr>
</table>
<vehicle-details [vehicle]="selectedVehicle"></vehicle-details>
Let’s call npm start and see how it looks:
You can try editing any value under the “properties” and the change will be immediately reflected in the table, nothing extra needed for it! Perfect.
It looks pretty good now, but it’s a bit difficult to determine which row is selected. Let’s fix this. Add an attribute [class.selected]="vehicle === selectedVehicle"
to the <tr> tag in vehicles-list.component.html. Its meaning is pretty obvious—add a CSS class for the case when the current row’s vehicle equals the selected one. Of course, to make this work, we need to add corresponding style to vehicles-list.component.css:
.selected { background-color: #CFD8DC !important;}
Let’s add hovering style too! It’s as easy as adding one line to the css file:
table.tftable tr:hover {background-color: #DDD; left: .1em;}
I haven’t done too much web development in my life. When I first started out as a developer, if you wanted anything more complex than just some static web pages with a navigation bar it required a lot of JavaScript coding. This proved quite a challenge with all that dynamic typing, a lack of a normal object model, and the headache of making it work and look as expected under different browsers. Now that I have returned to web development, I can definitely say that TypeScript is pretty awesome. It allows you to write almost any complex logic and it’s nearly as simple as Java—you are free to write your code and be “Java-ish”, making the classes/methods you want.
Angular also brings a huge improvement to web development. Now you can have natural HTML templates avoiding complex DOM manipulation and focus on creating components and UI. Angular CLI accelerates development by creating necessary component stubs using Angular best practices with just a single short command.
The recent release of Webclipse has added significantly better support for TypeScript, though the Eclipse community at large is still lacking a bit. I am excited about recent discussions on language server support inside Eclipse coming in the future!
Update: Since this blog was first published, Genuitec has released an Angular IDE with advanced support for both TypeScript and Angular 2. Stay tuned for an update to this blog where the project is completed with this new tooling. If you’re not already subscribing to our blogs, you’ll want to do that now.
vehicles.zip—Sample project for this blog
https://angular.io/docs/ts/latest/tutorial/—Tour of Heroes tutorial for Angular 2
https://cli.angular.io/—Angular CLI with commands description