In the last lesson, we walked through the areas of an Angular 2 app we're already a little familiar with such as npm, bower, TypeScript and Gulp.

This lesson will continue where we left off. We'll create the following Angular-specific pieces of our application, discussing each in detail along the way:

  • The root component.
  • The root module.
  • Configuration files for a tool Angular uses called SystemJS.
  • A main.ts file to launch the application.

At the end of this lesson, you should have your first functioning Angular application. Let's get started!

Root Component

Let's begin by building our first Angular component. Components are the basic building blocks of an Angular 2 app. They're reusable units of code that contain both visible front-end information to render to the user and any necessary back-end logic the elements it renders may require. Everything in Angular 2 is a component, including any navbar, sidebar and content.

Every Angular application requires at least one component called a root component. All other components will reside in this primary root component. An application may only have one root component.

Component HTML Tags

We'll include tags where we'd like our root component to be located in index.html. It's common practice to place it directly within <body>, like this:

index.html
...
<!-- 3. Display the application -->
  <body>
    <app-root>Loading...</app-root>
  </body>
...

As you may have guessed, <app-root> is not a standard HTML tag. This is a custom selector tag that refers to a particular component. It tells Angular where our component should be rendered. Once we finish creating it, our root component will load its template HTML between the <app-root> tags included above. (The tag name does not have to be app-root specifically. See more below.)

Component Files

These tags don't create a component; they simply instruct Angular where to place one. We'll create our corresponding <app-root> component now.

In the project directory, create a folder called app and a app.component.ts file inside it. This is the standard file name for root components.

Import Statements

Component files must import code from the Angular framework. This provides them access to everything they need to "know" to function as a component. We'll add this line to the top of our file:

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

As we'll see in future lessons, most Angular files contain import statements at the top just like this one. They retrieve portions of the core Angular code our files require.

Annotation

Every component has two distinct parts: an annotation and a class definition. Let's begin with the annotation. We'll place it into our component file below our import statement, like this:

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

@Component({
  selector: 'app-root',
  template: `
  <h1>My First Angular 2 App</h1>
  `
})
  • @Component is known as a decorator. Decorators are special pieces of syntax that configure elements like components. The decorator above tells Angular that the code following it defines a new component and should therefore have the functionalities outlined by Angular's own Component code imported at the top of the file.

  • selector: 'app-root' defines what tag corresponds with the component. Because we want this root component rendered within the <app-root></app-root> tags in index.html, the component's selector property must also be app-root. A component's selector determines what its corresponding tags will look like.

For instance, if this line instead read selector: 'super-crazy-component', we would be required to use the tags <super-crazy-component></super-crazy-component> wherever we wanted to render the component.

...
template: `
  <h1>My First Angular 2 App</h1>
`
}) 
  • The template portion (above) provides the HTML that will be displayed wherever the component is placed. Because we've defined our root component's selector property as app-root, the HTML listed in the template property will be rendered wherever the <app-root></app-root> tags are placed. We placed ours directly in the <body> tags of index.html. So, the HTML <h1>My First Angular 2 App</h1> will render in those same <body> tags.

Also, notice the backticks (`) at the beginning and end of the HTML above. This is a feature of ES6 that allows us to include multi-line strings without escaping quotes. Make sure to include these around any template code you include in your component files.

Everything we've just added is part of the component's annotation.

Component Class Declaration

Remember, every component requires two distinct parts: an annotation and a class definition. We just created our component's annotation. Let's declare its class definition next.

The class declaration includes the component's functionality. Add an AppComponent class declaration beneath the annotation we created in the last step. This is the standard naming convention for the root component's class.

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

@Component({
  selector: 'app-root',
  template: `
  <h1>My First Angular 2 App</h1>
  `
})

export class AppComponent { 

}

The class declaration will contain logic to define the component's behavior. For instance, when we build a To Do List in Angular, we'll create a component to display information about each Task. The template will display its description and a checkbox to mark a Task complete.

The class declaration will contain a method to actually update that Task's complete property when the checkbox is selected. The class annotation, where our template property resides, determines how a component appears, whereas the class declaration defines how it behaves.

Root Module

In addition to components, Angular applications also contain modules. Modules are used to organize areas of an Angular application into cohesive areas of functionality.

Imagine that a large Angular 2 application is like a large company. Modules are like the different departments in this company. A huge company has many, many different departments while a small one may only have one or two. Departments are physically organized into their own offices (or even their own buildings). And while each works for the same company, they have a unique, cohesive purpose and require their own special equipment to work toward that purpose.

A module may contain multiple components (and other stuff we'll learn about later like directives, pipes, and services). These are similar to the equipment and employees that belong to a specific department of a company. A component, on the other hand, can only belong to one module, except for a few very advanced special circumstances. This is similar to how an employee generally belongs to only one company department outside of a few special circumstances.

Every Angular application requires at least one module called a root module (this is like our "company headquarters"). This file will also be responsible for loading other parts of our app and any Angular-specific dependencies. Essentially, the root module instructs Angular how to assemble our application.

This week our applications will not yet become large enough to require multiple modules. For now, we'll only use a single, default root module.

Import Statements

First, we'll create a new app.module.ts file in app. This is the standard naming convention for root modules. Then we'll add the following import statements:

app/app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';

Similar to the import statements in our root component file, each of these imports a portion of the Angular framework's core library.

  • NgModule imports general Module code from the Angular framework's core.
  • BrowserModule imports code necessary to run our app in the browser, including built-in directives that allow us to add things like conditionals and loops to our components. We'll explore these soon.
  • AppComponent actually refers to the root component we created! We call it AppComponent because that's the name of the class declaration exported at the bottom of its file.

Module Decorator

Next, we'll add an @NgModule decorator just like we added a @Component decorator in our root component. This tells Angular that the code following this decorator is a module. However, the content within the decorator will differ from that in the component decorator:

app/app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
  • imports (the one directly below @NgModule) is an array of other modules and content this module requires. Here, we import a built-in module called BrowserModule. Note that this imports array differs from the import statements at the top of the file. The import statements at the top import functionality from the Angular core. The imports array under the decorator imports other pieces of our application we want included in this module.

  • declarations is an array of all components that will reside in this module. Because we only have one root component, we only list AppComponent here. (Things called pipes, directives, and services can also be included. We'll address this later, when we learn about these other Angular objects.)

  • In programming, the term "bootstrapping" refers to launching an application with the minimum required resources. It has nothing to do with the front-end framework Bootstrap that we use to style our sites. Here, bootstrap is an array of components required immediately upon launching the application. Because our page will use our root AppComponent right on the index, that component must be available as soon as the application boots up.

Class Declaration

Similar to our root component, the root module also requires a class declaration. We'll export the class AppModule at the bottom of the file. It will remain empty for now:

app/app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';

@NgModule({
  imports: [BrowserModule],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

AppModule is the standard name for the root module's class declaration.

Entry Point File

Finally, we need to add one more setup file to your app folder called main.ts. Known as an entry point, this file is responsible for instructing Angular's SystemJS tool exactly how to assemble our application when we launch it. It will load our root module, which then loads our root component.

app/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

const platform = platformBrowserDynamic();

platform.bootstrapModule(AppModule);

Again, the word bootstrap above here does not refer to the Bootstrap CSS framework. It refers to "bootstrapping", or launching, an application.

We will only ever need one main.ts file. This is the entry point. That is, the code that launches, or "enters" the application.

SystemJS Configurations

We need one last file. This file will contain configurations we'll rarely touch again. Add systemjs.config.js to the top level of your project directory and place the following code into it:

systemjs.config.js
/**
 * System configuration for Angular 2 samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',
      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      // other libraries
      'rxjs':                       'npm:rxjs',
      'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      },
      'angular2-in-memory-web-api': {
        main: './index.js',
        defaultExtension: 'js'
      }
    }
  });
})(this);

The code above is taken directly from the Angular documentation. Angular uses a tool called SystemJS internally. It's responsible for loading modules. This configuration file allows SystemJS to load modules that have been compiled by the TypeScript compilers.

Additionally, the line main: './main.js' informs SystemJS to launch the compiled main.js version of our main.ts file that includes instructions for launching our application.

Development Commands

Let's try it out! Run the following commands from the top level of your project directory:

  • $ npm install
  • $ bower init
  • $ bower install
  • $ gulp build
  • $ gulp serve

And, we should see our application live at localhost:3000!

first-launch

These are the same 4 commands that we will use to run any Angular project any time that we clone it from GitHub, at any stage in the development process.

Bower Dependencies and Live Reloading

If you open the console, you may also see errors about index.html being unable to locate vendor.css and vendor.min.js:

console-errors-launching-angular-app

This is normal. We haven't installed any bower dependencies, so vendor.css and vendor.min.js were not created when we ran $ gulp build.

Let's test our Bower build tasks by installing Bootstrap. Visit to the terminal window where you ran $ gulp serve and stop the server by pressing CTRL C. Then, run the usual bower command for installing a dependency:

$ bower install bootstrap --save

Now, we can run our build and serve tasks again to re-build and launch the project with its new bootstrap dependency:

$ gulp build
$ gulp serve

We should see the text in our blue <h1> has changed to Bootstrap's standard, sans-serif font:

adding-bootstrap

We can leave the $ gulp serve task running as we develop. If the compiler catches TypeScript errors, it will warn us in three places: Our text editor, the terminal our server runs in, and the browser.

The server will (generally) continue running when errors occur, allowing you to fix them, and then when we modify our files Gulp will automatically recompile and reload our server. Check your console window periodically to be sure you are seeing the latest code changes.

We can test our Bower dependency and our live-reloading development server by adding a <div> with the "container" class around our <h1> in our root component template, like this:

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

@Component({
  selector: 'app-root',
  template: `
  <div class="container">
    <h1>My First Angular 2 App</h1>
  </div>
  `
})

export class AppComponent { 

}

As soon as we save the file, our watch tasks will recompile our TypeScript for us and reload the browser. You should see that the margins have changed in the application.

Summary

The last two lessons covered a lot of territory. However, you are not required to memorize this process. It's absolutely fine and even expected if you aren't yet completely certain what each individual piece of an Angular application is responsible for.

Over the next few days in class, we'll revisit these setup instructions as we begin new projects. With each new application you create, the information presented in the past two lessons should become clearer.

If you'd like to explore additional resources, check out this free web series: The Net Ninja's series on Angular 2.


Example GitHub Repo for Angular 2 To Do List