Getting Started with Angular CLI

by Jason Swett,

One of the main things I liked about Rails when I first started using it was its command line interface. You get so much leverage by being able to scaffold a whole resource with just one command.

I was very happy when I learned about Angular CLI, which is currently in beta. I’ve been using Yeoman for Angular 1 but as far as I’ve been able to tell so far the Yeoman generators aren’t quite caught up with Angular 2. It’s nice to have a tool for Angular 2 that helps me understand how to structure my project, how to get tests set up, and all that nuts-and-bolts stuff that I don’t want to have to think about when I’m trying to quickly get familiar with a new technology.

In this tutorial I show you how to spin up a sample Angular 2 project on a Rails backend. Since the focus is on Angular and not Rails, I’ve provided a Rails repo for you so you don’t have to think about the Rails part too much.

Setting up the project

You can use my repo as a starting point. We’ll blow away and then rebuild the Angular portion but keep the Rails portion.

$ git clone git@github.com:jasonswett/dream_cars.git
$ cd dream_cars

CD into the project directory, create a new branch for this tutorial, then blow away the Angular code (which I always keep in the “client” directory as my own personal convention).

$ cd dream_cars
$ git checkout -b tutorial
$ rm -rf client
$ git commit -a -m"Delete contents of client directory."

Install the angular-cli package globally.

$ npm install -g angular-cli

Spin up a new Angular 2 project using ng new.

$ ng new dream-cars

Since for my Angular/Rails projects I always keep my Angular code in client, let’s rename dream-cars to client.

$ mv dream-cars client
$ cd client
$ rm -rf .git

We can run ng serve to start a server on port 4200.

$ ng serve

If you navigate to http://localhost:4200, you should see a message that says, “dream-cars works!”

Adding the Car component

Generate the car component.

$ ng generate route car

Modify your src/app/dream-cars.component.html to look like this. What we’re doing here, of course, is adding some navigation links.

<h1>{{title}}</h1>

<nav>
  <ul>
    <li><a [routerLink]="['/']">Home</a></li>
    <li><a [routerLink]="['/car']">Cars</a></li>
  </ul>
</nav>

<router-outlet></router-outlet>

If you go to your browser and click on the “Cars” link, you should see “car works!”.

Pulling in some data from the server

I already have migrations and seed data set up for you in the Rails project. All you have to do is run rake db:setup and start the rails server.

$ rake db:setup
$ rails server

If you navigate to http://localhost:3000/api/cars.json, you should see some data.

Modify src/app/+car/car.component.ts to look like this.

import { Component, OnInit } from '@angular/core';
import { Http, HTTP_PROVIDERS } from '@angular/http';

@Component({
  moduleId: module.id,
  selector: 'app-car',
  templateUrl: 'car.component.html',
  styleUrls: ['car.component.css']
})
export class CarComponent implements OnInit {
  cars: any;

  constructor(public http: Http) {}

  ngOnInit() {
    this.http.get('/api/cars.json')
      .subscribe(response => this.cars = response.json());
  }

}

Notice the cars: any part. That’s probably not the way that should be done. Frankly, I don’t know the right way to do that yet. I’m learning too.

In order for Http to work, you’ll have to add it to your application’s bootstrap in src/main.ts.

import { bootstrap } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { DreamCarsAppComponent, environment } from './app/';
import { Http, HTTP_PROVIDERS } from '@angular/http';

if (environment.production) {
  enableProdMode();
}

bootstrap(DreamCarsAppComponent, [HTTP_PROVIDERS]);

If you now navigate to http://localhost:4200/car, you’ll get an error. This is because our HTTP request is trying to go to http://localhost:4200/api/cars.json, which doesn’t exist. We need http://localhost:3000/api/cars.json.

To make our Angular server on port 4200 talk to our Rails server on port 3000, we can use a proxy. Kill your Angular server process and run this instead:

$ ng serve --proxy http://localhost:3000

This tells the server to route all XHR requests to port 3000. If you refresh the browser, you should no longer see the error.

There’s another problem, though. If you look at the log output for both the Angular server and the Rails server, you’ll see some wacky errors flying across the screen. This has to do with source map files not being included in /dist. You can fix the problem by modifying angular-cli-build.js in the following way.

/* global require, module */

var Angular2App = require('angular-cli/lib/broccoli/angular2-app');

module.exports = function(defaults) {
  return new Angular2App(defaults, {
    vendorNpmFiles: [
      'systemjs/dist/system-polyfills.js',
      'systemjs/dist/system.src.js',
      'zone.js/dist/*.{js,js.map}',
      'es6-shim/es6-shim.js',
      'reflect-metadata/*.{js,js.map}',
      'rxjs/**/*.{js,js.map}',
      '@angular/**/*.{js,js.map}'
    ]
  });
};

With that out of the way, let’s edit our src/app/+car/car.component.html to allow our car data to be shown.

<ul>
  <li *ngFor="let car of cars">
    {{ car.year }}
    {{ car.make }}
    {{ car.model }}
  </li>
</ul>

<car-form></car-form>

If you navigate to http://localhost:4200/car, you should now see something like the following, with a list of cars.

dream cars

There’s a lot I’ve skipped in this tutorial. There are probably some things I’ve done improperly. This is meant to be a quick and dirty intro to Angular CLI so you can get a real full-stack application functioning so you can start tinkering and making progress with Angular 2.

Leave a Reply

Your email address will not be published. Required fields are marked *