Angular: Getting Started

Kevin O'Shaughnessy
21 min readMay 21, 2016

--

Welcome to this review of the Pluralsight course Angular: Getting Started by Deborah Kurata.

Deborah is an independent software designer/developer specializing in Web and .NET development using AngularJS, C#, and VB.NET. She has won the Microsoft Most Valuable Professional Award 16 times.

Over the last 3 years, this has remained one of the most popular and frequently watched courses in the whole of the Pluralsight library.

Originally known as “Angular 2: Getting Started”, it has been updated five times as newer versions of Angular have come out. Since Angular v4 was released, the framework has usually just called been called Angular (without the number on the end). It was given a minor update for Angular version 7 in November 2018 and previous had more widespread changes for the RxJS v6 and Bootstrap v4 changes associated with Angular 6 in July 2018.

At the time of writing, the most recent version of Angular is version 8. I suspect Deborah that will be releasing a small update for this soon, but there will not need to be any major changes for it.

This course is now part of Pluralsight’s Angular learning path, and is the second course on the path, following Joe Eames Angular: The Big Picture course (which is a short course that I can recommend for giving yourself a quick overview). The course is 5 hours 41 minutes long and covers many different Angular concepts which you can use to build advanced web applications.

The course uses Visual Studio Code as the editor, but if you like using Visual Studio 2015, check out Deborah’s post Angular 2 Getting Started With Visual Studio 2015.

If you don’t have (and don’t want) a Pluralsight subscription, you’ll find that the official Angular documentation is very good and as long as you don’t rush, you should be able to follow it okay.

I actually think one of the best things about Angular is that it has very clear and up to date official documentation, because a lot of open source software is very lacking on quality documentation.

Related Courses and resources

John Papa released a shorter Pluralsight course in 2016 called Angular 2: First Look. I recommended this course when I first reviewed it, but now we are in 2019 I think it is better to follow the Pluralsight Angular learning path.

An alternative guide to Angular 2 Core Concepts that I found useful is from Victor Savkin.

Deborah has also produced an intermediate level course on Angular Component Communication.

Angular 2 supports browsers as old as Internet Explorer 9, but is mostly aimed at developers interested in programming using the latest technology. This is why, like React JS, we tend to see new technologies (such as Babel for Transpiling from the latest ES 2015 code to ES5) used alongside it.

Wherever you see the word foo in the examples, substitute it with any word you want to use. Where you see … it means I have skipped some code for brevity so that I can highlight the concept without the code clutter.

Introduction

This aim of this course is to get you up to speed quickly with Angular components, templates and services.

Deborah begins by introducing Angular as a Javascript framework for building client-side applications. She says it makes our HTML more expressive, has powerful data binding, is modular by design, and has built-in back-end integration.

Deborah also asks the question “with so many developers using Angular JS (Angular version 1), why do we need a new Angular?”

She answers this question saying Angular is/has:

  • Built for speed
  • Modern
  • Simplified API
  • Enhances productivity

Anatomy of an Angular application

Angular applications are comprised of a set of components, and services that provide functionality across them.

Deborah explains what an Angular component is made up of:

  • templates (defining a view)
  • classes (with properties and methods, defining the code)
  • metadata.

She also covers the role of modules and their relationship with components.

Prerequisites

Deborah says you should know JavaScript, CSS and HTML.

No essential, but helpful, is a knowledge of object oriented programming concepts.

You don’t need any prior knowledge of Angular or TypeScript.

Blog

Deborah’s blog is at http://blogs.msmvps.com/deborahk/ and contains further information about this course. She recommends checking this out if you are having problems with the code for this course.

GitHub Repository

You can find the Angular — Getting Started sample application on Github.

Sample Application

Deborah demonstrates the final sample application. It’s an “ACME product management” app for managing a list of products.

We see there is a “show image” button and clicking on it reveals thumbnail images of each product. The table shows Product, Code, Availability Date, Price and 5 Star Rating.

Above the table is a product filter textbox control.

We can also click on the product name link to go to the relevant product detail screen.

Deborah explains all of the components that will be involved in creating this app.

First Things First

This module covers things we need to decide before we start coding.

Selecting a Language

Deborah describes the following options that we have:

The “language” used in this course is TypeScript. If you’ve not come across it before, Deborah explains what this is here.

She recommends trying out the TypeScript Playground

In Joe Eames Big Picture course he says you wouldn’t want to NOT use Angular without TypeScript. Based on my experiences and discussions with various people over the years, I entirely agree with this. If you want to learn Angular, learn TypeScript as well if you don’t already know it.

Deborah mentions three Pluralsight courses that are useful for learning TypeScript. I have also reviewed Steve Ognibene’s Practical TypeScript Migration course for you.

Selecting an Editor

The following editors (and others) can work with TypeScript:

  • Visual Studio
  • Visual Studio Code
  • WebStorm
  • Atom
  • Eclipse
  • Sublime Text

Deborah uses Visual Studio Code in this course.

Setting up our environment

We learn how to install npm, and set up the Angular application.

Deborah introduces Angular CLI as command line tool for generating setup files and boilerplate code for an Angular application.

Setting up an Angular application involves:

  1. Creating an application folder
  2. Adding package definition and configuration files
  3. Installing the packages
  4. Creating the app’s Angular Module
  5. Creating the main .ts file
  6. Creating the host web page (index.html)

Using the Angular CLI is easier than performing all these steps manually. However the easiest thing for beginners to do is to copy the files from Deborah’s starter project on Github. This includes a package.json file which contains all the dependencies we need.

We see that we can type “npm install” in the Node console to download all the node modules that we need.

Running an Angular application

We see that we can run it from the Node console by typing “npm start”.

We see that the application is configured to watch for changes so whenever we save a change the build is automatically kicked off again. In fact, Deborah has Visual Studio Code configured to auto save, so we see automatically see the changes shortly after we make them.

About Modules

You will want to watch this as it can be confusing with all of the different types of modules in use in the world of JavaScript. Deborah explains that we have:

  • Angular JS modules
  • TypeScript modules
  • ES 2015 modules (a.k.a. ES6 modules)
  • Angular modules

Angular makes use of ES 2015 modules. Deborah summarizes by saying ES modules are about code files, and Angular modules are about our application.

Introduction to Components

This module builds our first component, the “App component”.

What is a component?

An Angular component is made up of a:

  • Template (for view layout, created with HTML, with bindings and directives)
  • Class (code supporting the view, with properties for data and methods for logic)
  • Metadata (defined with a decorator)

We see an example app.component.ts. It has the following elements:

  • Import (of angular core’s components)
  • Metadata and template
  • Class (being exported)

Creating the Component Class

We define a class using the class keyword, followed by the class name.

It’s a convention in Angular to add the word Component as a suffix, e.g. AppComponent.

Deborah covers methods, property names, data types and default values.

Defining the Metadata with a Decorator

A decorator is a function that adds metadata to a class, its members, or its method arguments. It’s always prefixed with the @ symbol.

Decorators have been proposed by wycats as a JavaScript feature. It has been implemented in TypeScript.

A common use of the decorator in Angular is in the component declaration:

@Component()

Deborah introduces the directive name, view layout and binding here.

Importing What We Need

The import statement is part of ES 2015 and implemented in TypeScript.

This page shows all of the Angular 2 modules that we can import:

https://www.npmjs.com/~angular

Demo: creating the App Component

We look again at app.component.ts

import { Component } from '@angular/core'; @Component({ 
selector: 'pm-app',
template: `<div>
<h1>Hello world</h1>
</div>`
})
export class AppComponent {
pageTitle: string 'Your App Name';
}

Bootstrapping Our App Component

Here Deborah looks at the steps for hosting an application, and defining the Angular module. There’s a 4 minute demo to illustrate these concepts.

Checklists and Summary

Deborah concludes the introductory components module with a checklist of tips for working with components.

This is useful if you are new to Angular as it will help you to avoid making common mistakes.

Other Web Components

If you are interested in using web components without using Angular, check out Polymer and X-Tag

Templates, Interpolation and Directives

Building a Template

The previous module defined a simple inline template, with a multi-line string, directly inside a component.

For better syntax checking and highlighting, we can instead create a linked template with the template in its own HTML file. Deborah shows us how we use the templateUrl property to do link to this.

We also see a preview of what we’ll be building: a product list view with columns for Product, Code, Available, Price and 5 Star Rating. This demo will use Bootstrap and Font Awesome in addition to Angular to make it look nice, and Deborah installs these with npm and imports the styles into into styles.css in this clip.

We also see the creation of product-list.component.html and this is a table with the table body left empty.

Building the Component

In our component declaration we are using templateUrl: ‘./product-list.component.html’ and we see how to create the TypeScript to accompany the template.

Using a Component as a Directive

Here Deborah discusses the relationship between the BrowserModule, AppModule, AppComponent and Product-List component.

We get our first sighting of an Angular error message here:

Uncaught Error: Template parse errors:
'pm-products' is not a known element:
If 'pm-products' is an Angular component, then verify that it is part of this module

This problem is solved by simply adding ProductListComponent to the @NgModule declarations array. We can use VS Code to write our import for us, saving us from manually typing it out.

Binding with Interpolation

Binding coordinates communication between the component’s class and its template and often involves passing data. It is done using the double curly brace {{ handlebars }} or {{ moustaches }} depending on what you prefer to call them.

Adding Logic with Directives: ngIf

We begin adding logic to our template with the *ngIf structural directive, which is used for if logic:

<tr class='table' *ngIf='products && products.length'>

Adding Logic with Directives: ngFor

Next we add some more with the *ngFor structural directive.

<tr *ngIf=’let product of products’>
<td>{{ product.productName }}</td>
<tr>

Checklists and Summary

We get a summary of this module in checklist form. Pay close attention to the syntax!

Data Binding and Pipes

Deborah explains that we want to combine DOM elements to component properties so that our components can change their look and feel as needed. This is illustrated as properties going into the DOM

We also want notifications of user actions and other events from the DOM into our component. A simple example a component getting notified by a button click event, so that the component can show or hide an image.

The architectural design of the product list tool we build in this course is as follows: The index.html view uses the AppComponent.

This is the top level component and it is made up two smaller components: a Welcome component and a Product List component. The Product List component contains a Product Detail component, and both the Product List and Product components use a Star component.

Property Binding

Deborah shows several different syntax we can use for property binding in our Templates.

We can either use the {{ handlebars }} or do
<img [src]=’product.imageUrl’>

We get our images showing on screen, but they’re huge, so we also see how to add imageWidth and imageMargin style properties.

Once applied, the images look nice. We need to get the show/hide images button working next.

Handling Events with Event Binding

Up to now all the data binding has been in one direction: binding from the TypeScript code to the template properties.

Here we want to bind in the other direction to respond to our button clicks.

<button (click)='toggleImage()'>

Deborah shows us how to write the toggleImage function in TypeScript. We also see that we can use interpolation to update the button text from ‘Show Image’ to ‘Hide Image’ and vice versa.

{{ showImage ? 'Hide' : 'Show' }} Image

For the filtered by textbox, we’ll need to use Two-Way Binding

Handling Input with Two-Way Binding

Put the banana…
…in a box, to perform Two-Way data binding!

This is where we first see the ‘banana in a box’ syntax.

<input [(ngModel)]='listFilter'>

We get another Angular console error in this clip:

Can't bind to 'ngModel' since it isn't a known property of 'input'

This means Angular cannot find the ngModel directive. ngModel is part of the Angular FormsModule. To access the FormsModule from our product list component, we add this to app.module.ts:

import { FormsModule } from '@angular/forms';

Transforming Data with Pipes

Pipes are used to transform bound properties before display. We can chain pipes together, for example to display some text as a currency in lowercase:

{{ product.price | currency | lowerCase }}

Some pipes have parameters.

Checklist and Summary

When using NgModel, remember to define it within the banana in a box fro two-way binding. Add FormsModule to your imports array in the appropriate Angular module.

More on Components

Deborah introduces this next module by saying we can improve our components with the following practices:

  • Strong typing and interfaces
  • Encapsulating styles
  • Use lifecycle hooks
  • Building custom pipes
  • Use nested components

Defining Interfaces

We’ve been using the any keyword with our products list up until now, which does not give us strong typing. We can specify a strong type by defining an interface.

Interfaces are a TypeScript concept: it is not a feature of regular JavaScript.

See products.ts for an example of a TypeScript interface. In this clip we see how much easier Intellisense makes it for fixing problems.

Encapsulating Component Styles

Templates sometimes require unique styles.

The component decorator has two properties to encapsulate styles as part of the component definition: styles and styleUrls

Deborah recommends using the styleUrls property to link to external stylesheets, and has an example in product-list.component.ts

Using Lifecycle Hooks

  • Create
  • Render
  • Create and render children
  • Process changes
  • Destroy

This is the first thing that I found to be a little less than intuitive. You just have to learn the syntax for this. These are some interfaces used for TypeScript that you won’t need if you are using plain JavaScript:

OnInit does the component initialization. It executes custom initialization logic after your directive’s data-bound properties have been initialized.

You need to remember to use ngOnInit and ngOnDestroy inside your class definition.

Here’s a live example on plunker, click on app.ts to see the use of OnInit and OnDestroy. Also see OnInit interface docs

We can use the OnInit lifecycle hook to perform any component initialization after Angular has initialized the data bound properties. An example is product-list.component.ts where our ProductComponent implements OnInit, which means the component needs a ngOnInit() method

The OnChanges hook performs an action after there a change to one or more input properties

The OnDestroy hook performs cleanup work before Angular destroys the component

See the official Angular Core documentation for:

Building Custom Pipes

If there isn’t a built in pipe available, you can create your own custom pipes.

Something that Deborah doesn’t mention which is quite important is pipes can either be pure or impure, and impure pipes are more complex than pure ones. Joe Eames covers this in his Big Picture course Gotchas section.

Angular has built-in pipes such as:

In this clip we want to create a custom pipe that displays the post code with a space instead of a hyphen. Its called ConvertToSpacesPipe and the TypeScript code is here. It does a simple transformation, replacing a specified character in a string with the space character.

We must remember to add our new pipe to @NgModule

Filtering a List

The Angular team recommend moving sorting and filtering logic into the Component itself, as opposed to using Pipes.

Building Nested Components

In this module we learn how to build components that are designed to be nested within other components.

Building a Nested Component

Our sample application currently displays the 5 star ratings as numbers.

We want to replace this with star images by creating a Star Component which uses a Font Awesome star icon. We use a starWidth property to show the appropriate amount of stars. The starWidth will be calculated based on the rating.

Using a Nested Component

Deborah sets the starWidth in the ngOnChanges method in our star component.

With our initial implementation we see 5 stars when we expected to only see 4 stars.

Deborah explains that our OnChanges event is not firing, and we don’t currently have a way to get the correct rating number from the container.

Passing Data to a Nested Component

In this clip we learn about the @Input decorator, and we add it to the rating property in our Star Component.

In our template, we use property binding and define the nested component’s input property as the target of the target of the binding:

<pm-star [rating]='product.starRating'></pm-star>

Our ngOnChanges method will now get fired when the container data changes.

Passing Data from a Component

In this clip we learn about the @Output decorator. Deborah explains that the property type must be an event: a nested component can only pass data back to its container is with an event.

In Angular we define this with an EventEmitter object.

We create an onClick method in the star component and console log the star rating that was clicked. Then we enhance the code with the emit method.

In our template we listen for the ratingClicked event, and when the event is raised we call a new method onRatingClicked($event)

star.component.ts

import { ... EventEmitter } from 'angular/core';
@Component({...})export class StarComponent {

@Input() rating: number;
starWidth: number;
@Output() notify: EventEmitter = new EventEmitter();
ngOnChanges(): void { this.starWidth ...}

}

Checklists and Summary

This clip has a checklist for input and output decorators. Remember to begin with the @ symbol and end with the () parentheses, and use the new keyword when creating an instance of EventEmitter.

Deborah mentions her intermediate level course Angular Component Communication contains more in depth material on components.

Services and Dependency Injection

Services are used for things that we want to share across components, and may not be associated with any particular view.

Deborah defines a service as a class with a focused purpose.

So far our app has data hardcoded into our product list component.

How does it work?

There are two ways a component can work with a service:

  1. The component can create an instance of the service class (instance is local to the component)
  2. Register the service with the Angular injector.

Building a service

The basic steps follow the same pattern as we’ve seen for the components and pipes already:

  1. Create the service class
  2. Define the metadata with a decorator
  3. Import what we need

See products.service.ts for an example of an Angular service which reads data from a JSON file.

Deborah says a service is just an ordinary class until we register it with an Angular injector. We do this in the next clip.

Registering the service

There are actually two kinds of injectors.

The root injector ensures that the service is available throughout the entire application, and is recommend in the most cases.

The component injector makes the service available only to that component and any of its child components. Provides multiple instances of the service.

We define the type of injector that we want inside the Injectable decorator with the providedIn property (this was introduced in Angular 6 and gives us better tree-shaking than the older method).

We register the service in our component using the providers property.

Injecting the service

Now that we have a registered service, we want to define it as a dependency, so that the injector will provide the instance in the classes that need it.

In TypeScript, we use the constructor() function to do our dependency injection. So in product-list.component.ts we import the ProductService and inject it using the constructor function.

Retrieving Data Using HTTP

Observables and Reactive Extensions

Observables help us manage asynchronous data. They treat events as a collection.

We can subscribe to an observable to receive asynchronous notifications as new data arrives.

Deborah shows us an example of using the map operator, based on the rxmarbles site.

The rxmarbles site is very useful for learning rxjs operators. You can drag the marbles across the timeline and see what effect it has. The reactiveX documentation also let’s you do this.

In this clip we see the effect of using map and filter with a pipe. Deborah also covers the differences between Promises and Observables. Whereas a promise provides a single future value, an observable emits multiple values over time. Observables have advantages over Promises such as lazy behaviour, the ability of cancel them, and support for many operators.

See Observables compared to promises.

Sending an HTTP request

Angular provides us with an HttpClient class with methods for all the HTTP verbs that we want to use.

The get() method makes it easy to receive JSON data.

We look at the getProducts() method in product.service.ts — this returns an Observable of IProduct[]. This array contains only one element.

There’s a 3 minute demo where Deborah adds an import of the HttpClientModule to app.module.ts, and imports HttpClient and Observable to product.service.ts. Then we replace the hardcoded JSON data with a call to the http get method.

We see an error message and Deborah says we need to add Exception handling.

Exception Handling

This clip teaches us a couple of RxJS operators: tap and catchError

First we learn about tap operator. In the ReactiveX documentation this links to the Do operator.

It taps into the observable stream and allows us to look at the emitted values in the stream without transforming the stream.

Both tap and catchError are passed in as parameters into a pipe method.

Subscribing to an Observable

There are three overloads for the subscribe method:

x.subscribe(nextFn)
x.subscribe(nextFn, errorFn)
x.subscribe(nextFn, erroFn, completeFn)

The subscribe method returns a subscription, and we can call cancel on it if we no longer want to subscribe to the observable.

See the ngOnInit method in the product list component for an example of subscribing to an observable. There is a 4 minute demo showing how it’s done.

Deborah concludes by reiterating that the recommended way to use HTTP is to encapsulate it in a service.

Navigation and Routing Basics

So far in this course, everything has just been on one screen. The aim of this module is to produce an application the routes to multiple views.

Generating Code and Handling Undefined

We want to build a product detail component, which will display an image of the product as well as other product information.

We can use Angular CLI to do much of the work for us. You install the CLI with the command:

npm install -g @angular/cli

Once installed we generate a component like this:

ng g c products/product-detail --flat

This creates four new files:

  • product-detail.component.html
  • product-detail.component.spec.ts
  • product-detail.component.ts
  • product-detail.component.css

It also updates our app.module.ts file for us.

The generated html file merely contains the placeholder html

<p>product detail works!</p>

We replace this with

<div class=”card”><div>
{{ pageTitle + ': ' + product.productName }}
</div></div>

Because http works asynchronously, we may not have product available at the time Angular tries to display it.

So Deborah teaches us some ways to avoid getting an undefined property error. The first solution is the safe navigation operator.

The equivalent in C# is known as the null-coalescing operator. It is a terse way to protect against accessing properties on objects with null or undefined values.

product?.productName

Deborah warns that this technique does not work with the ngModel two-way binding, and says it can get repetitive if there are a lot of properties to display.

Instead we can use *ngIf=’product’

Deborah also shows us how to manually add another component, adding the WelcomeComponent to the @NgModule declarations array.

How Routing Works

Angular uses HTML5 style URLs which don’t need the # symbol to indicate local navigation. For example myWebService.com/products

You will need to configure your web server to perform URL rewriting. How to do depends on the web server you are using, and this is outside the scope of the course.

Angular also supports # style URLs which do not require URL rewriting. For example: myWebService.com/#/products

Configuring Routes

We need to add import the RouterModule to our app.module.ts file and add RouterModule to our @NgModule imports array.

If we want to use the hash style URLs we do:

RouterModule.forRoot([], { useHash: true })

Deborah explains how to configure the routes that we want by adding objects to our forRoot array.

The order matters because the router uses a first match wins strategy.

Tying Routes to Actions

User actions such as menu options, clicking links, images or buttons, should activate new routes.

This clips shows us how to tie routes to user actions using the routerLink directive.

Placing the Views

How do we specify where we want the routed component to display its view?

We use the router-outlet directive.

Deborah updates the template in app.components.ts

Checklists and Summary

Routing checklist:

  • Define the base element
  • Add RouterModule
  • Add each route
  • Remember that order matters
  • Be sure the path has no leading slash
  • Use an empty path ‘’ for a default route
  • Use ‘**’ for a wildcard route
  • For tying routes to actions, add the RouterLink directive as an attribute
  • For placing the view, Add the RouterOutlet directive

Navigation and Routing Additional Techniques

The last modules will be finished over the course of this week.

Passing Parameters to a Route

An example of passing parameters to a route is passing a product id to the products route so that we display the relevant product’s details.

We do this in the forRoot array. In the path property we finish with /:id

{ path: 'products/:id', component: ProductDetailComponent }

The value for the route parameter comes from the template:

<a [routerLink]="['/products', product.productId]">
{{ product.productName }}
</a>

To read parameters from a Route we use the ActivatedRoute service. This service is already registered as part of the RouterModule.

The ActivatedRoute is defined as a dependency of the product detail component, and the instance is injected into the component class.

In the demonstration, we see the product names are changed to hyperlinks.

Activating a Route with Code

We create an onBack() method in our product detail component, and in here we use the router navigate() method.

Protecting Routes with Guards

Guards can be used to restrict access to a route, or display a confirmation before routing to a new location. Guards in Angular include:

In this clip Deborah shows how to use the CanActivate guard.

In the demonstration, she explains that we want to ensure that the product id is numeric and not less than 0, and show us how we can use the Angular CLI to accomplish generate all the boilerplate code for us. The CLI also creates the start of a unit test for the guard.

The guard code can be found here.

Angular Modules

Deborah begins with a diagram that looks a bit like a train map: its a design for how we can setup our Angular modules. Currently everything is in the appModule, but we plan to create a ProductModule and a SharedModule.

What is an Angular Module?

An Angular module is a class with an NgModule decorator.

There are used to arrange the pieces of our application into blocks of related functionality. We can also use them to extend our application with capabilities from external libraries.

Deborah says an Angular module can either be loaded eagerly on app startup, or lazily and asynchronously, by the router.

An Angular module:

IMPORTS — @angular modules, Modules, 3rd party Modules, Route modules

EXPORTS — @angular modules, Modules, 3rd party Modules, components, directives and pipes

PROVIDES — Services

DECLARES AND BOOTSTRAPS — Components, directives and pipes

At this point in the course, we have an AppModule with imports for BrowserModule, FormsModule, HttpClientModule and RouterModule.

Bootstrap Array

  1. Every application must bootstrap at least one component, the root application component
  2. The bootstrap array should only be used in the root application module, AppModule

Declarations Array

  1. Every component, directive, and pipe we create must belong to one and only one Angular module.
  2. Only declare components, directives, and pipes
  3. Never redeclare components, directives, or pipes that belong to another module
  4. All declared components, directives, and pipes are private by default. They are only accessible to other components, directives, and pipes declared in the same module.
  5. The Angular module provides the template resolution environment for its component templates.

Exports Array

  1. Export any component, directive, or pipe if other components need it.
  2. Re-export modules to re-export their components, directives, and pipes.
  3. We can re-export something without importing it first (later we’ll be seeing the SharedModule exporting the FormsModule without importing it).
  4. Never export a Service

Imports Array

  1. Importing a module makes available any exported components, directives and pipes from that module.
  2. Only import what this module needs.
  3. Importing a module does NOT provide access to its imported modules (imports are not inherited).

Providers Array

  1. Any service provider added to the providers array is registered at the root of the application (not the case for lazily loaded services).
  2. Don’t add services to the providers array of a shared module. Consider building a CoreModule for services and importing it once into the AppModule.

Feature Modules

Deborah discusses creating a ProductModule that contains:

  • Product List component
  • Product detail component
  • ConvertToSpaces pipe
  • Star component

This is followed by a 4 minute coding demonstration which begins with the Angular CLI command: ng g m products/product — flat -m app

This creates the boilerplate files, and then Deborah adds the above components to the declarations array. We use the forChild method on the RouterModule to set the paths in product.module.ts

Shared Module

This is similar to what we did for the ProductModule.

We start with the Angular CLI command:

ng g m shared/shared — flat -m products.product.module

Revisiting AppModule

The AppModule is now much lighter, because we’ve moved code out into our new modules.

Building, Testing, and Deploying with the CLI

Angular CLI Overview

ng new

ng serve

ng generate

ng test

ng build

Final Words

Recapping our journey

Learning more

What is Angular (Revisited)?

--

--

Kevin O'Shaughnessy

Sr. Full Stack Web Dev promoting better professional practices, tools, solutions & helping others.