Lesson Weekend

Now that we can create and configure Angular applications using the Angular CLI tool, let's walk through the common actions and commands we'll use as we develop our application using Angular CLI.

In this lesson, we'll walk through how to build and serve a project with Angular CLI. We'll also discuss how to generate new components, pipes, and other content automatically through the command line. We'll explore how code in these automatically-generated pieces of our application may differ from what we saw last week when we created these files manually.

Building and Serving

Whenever we want to launch our project, we can do so with one command:

$ ng serve

This will print content into the command line:

$ ng serve
** NG Live Development Server is running on http://localhost:4200. **
Hash: 97fa437807e72ba9432f                                                               
Time: 9813ms
chunk    {0} styles.bundle.js, styles.bundle.map (styles) 161 kB {3} [initial] [rendered]
chunk    {1} main.bundle.js, main.bundle.map (main) 4.53 kB {2} [initial] [rendered]
chunk    {2} vendor.bundle.js, vendor.bundle.map (vendor) 2.84 MB [initial] [rendered]
chunk    {3} inline.bundle.js, inline.bundle.map (inline) 0 bytes [entry] [rendered]
webpack: bundle is now VALID.

Notice that our applications are now served on localhost:4200 instead of localhost:3000. This is because we're no longer using our Gulp task to serve the project. Now we're relying on Angular CLI's built-in tools, which serve on a different port.

If we navigate to http://localhost:4200, the browser politely informs us that our "app works!"

app-works

This text is coming from our root component:

src/app/app.component.ts
...
export class AppComponent {
  title = 'app works!';
}

We can stop the server at any time by pressing Ctrl + C.

Note that the server is live-reloading. We can make changes and see them automatically reflected in the browser.

For instance, we could change the text reading 'app works' to something else:

src/app/app.component.ts
...
export class AppComponent {
  title = 'Angular CLI is great!';
}

Refresh our page in the browser without restarting the server and you'll see the changes reflected immediately:

live-updating-demo

Adding new packages or changing any configuration will require a server restart before changes are reflected in the application.

Some errors and issues may cause the application or server to freeze, requiring a restart. Whenever you experience a bug or other issue, re-starting the server should be one of your first troubleshooting steps.

Linting Code

As we briefly mentioned in the last lesson, the Angular CLI also includes a built-in TypeScript linter. Just like the linter Gulp task we used in the first week of JavaScript, this will inform us of any syntax errors in our code.

We can run the linter with the $ ng lint command. If we do this now, we should see that it does not catch any errors:

$ ng lint

> [email protected] lint /Users/staff/Desktop/online-store
> tslint "src/**/*.ts" --project src/tsconfig.json --type-check && tslint "e2e/**/*.ts" --project e2e/tsconfig.json --type-check


All files pass linting.

When debugging, the ng lint command can help quickly locate syntax errors.

Creating New Parts of an App using Angular-CLI

We'll use Angular-CLI throughout the course of development to create new components, pipes, and other parts of an Angular app directly through the command line.

Let's create the first component in our online store. We can generate new components with the $ ng generate component component-name command (or $ ng g component component-name, for short) like this:

$ ng g component welcome

After executing this command, Angular will respond with a list of all files created and updated:

installing component
  create src/app/welcome/welcome.component.css
  create src/app/welcome/welcome.component.html
  create src/app/welcome/welcome.component.spec.ts
  create src/app/welcome/welcome.component.ts
  update src/app/app.module.ts

Angular-CLI creates a new directory called welcome within the existing app directory. welcome contains all files relevant to the new WelcomeComponent.

Let's walk through these new files:

welcome.component.css

This is where any styles specific to our new welcome component will reside. It's currently empty.

welcome.component.html

This is the HTML template for our new component. Angular-CLI has added test text in <p> tags for us:

src/app/welcome/welcome.component.html
<p>
  welcome works!
</p>

welcome.component.spec.ts

This is where any tests for our new component would reside.

welcome.component.ts

This is our component's main file, where its class declaration and decorator will reside. Angular-CLI has already filled in some boilerplate code for us:

src/app/welcome/welcome.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-welcome',
  templateUrl: './welcome.component.html',
  styleUrls: ['./welcome.component.css']
})
export class WelcomeComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

We're using the @Component decorator to define our component. The selector has already been defined as app-welcome, the templateUrl property already points to the welcome.component.html template file, and our WelcomeComponent class has been declared.

ngOnInit() and constructor()

Notice the class declaration is implementing the OnInit interface and has included an empty ngOnInit() method. This is one of Angular's Component Lifecycle Hooks. Lifecycle hooks are methods called automatically at certain points in an object's creation.

ngOnInit() is called internally by Angular whenever a component is initialized. If there was code we needed to execute as soon as a component was loaded, we could place it here.

We won't use the ngOnInit() method or OnInit interface until later this week. So, you can either remove these, or leave them empty each time you create a new component.

online-retail-store/src/app/welcome/welcome.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-welcome',
  templateUrl: './welcome.component.html',
  styleUrls: ['./welcome.component.css']
})
export class WelcomeComponent {

  constructor() { }

}

If you'd like to explore Lifecycle Hooks further, begin with the Angular Documentation.

Constructor

The WelcomeComponent class declaration comes with an empty constructor() method. This is called before ngOnInit(). It's used to run any logic that must occur before or while a component is being initialized. It's primarily used to set up something called dependency injection, which we'll explore in an upcoming lesson.

For now, you can remove this from any new components you generate:

src/app/welcome/welcome.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-welcome',
  templateUrl: './welcome.component.html',
  styleUrls: ['./welcome.component.css']
})
export class WelcomeComponent {

}

app.module.ts

The command to generate a new component will automatically update our root module to include our new component:

src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { WelcomeComponent } from './welcome/welcome.component';

@NgModule({
  declarations: [
    AppComponent,
    WelcomeComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

As you can see, WelcomeComponent is imported at the top of the file and included in the declarations array.

Structural Differences

Last week, we placed our component files directly into an app directory. Now components generated by Angular CLI reside in their own directories, like the welcome directory just added to our project.

Therefore, the file paths used to import components and other code will differ too. Notice the line importing our new component above: import { WelcomeComponent } from './welcome/welcome.component';

The filepath to the component now includes the welcome directory: './welcome/welcome.component'.

More Angular CLI Commands

There are many more commands to create new pieces of an Angular project directly from the command line. For instance, you can generate a new Pipe:

$ ng g pipe pipe-name

Or even a new class to use as a model:

$ ng g class class-name.model

Check out the Angular CLI Reference Guide for a list of all commands you can use with Angular's command line interface.