The internet seems to break annually, requiring developers to patch it up. Many anticipated that the release of Angular version 9 would follow suit, necessitating significant migration efforts for applications built on previous versions.
However, that’s not the reality! The Angular team revolutionized its compiler, yielding faster build and test execution, reduced bundle sizes, and crucially, backward compatibility with older versions. Essentially, Angular 9 delivers all the advantages without the usual headaches.
This Angular 9 tutorial guides you through building an Angular application from the ground up. We’ll utilize some of the latest Angular 9 features and explore other enhancements as we proceed.
Angular 9 Tutorial: Building a New Angular Application
Let’s embark on our Angular project example by installing the latest version of Angular’s CLI:
| |
Verify the Angular CLI version with the command ng version.
Next, create an Angular application:
| |
We’re employing two arguments in our ng new command:
--create-application=falseinstructs the CLI to generate only workspace files. This enhances code organization when dealing with multiple apps and libraries.--strictenforces stricter rules for TypeScript typing and code cleanliness.
This results in a basic workspace folder and files.

Now, add a new app:
| |
You’ll be prompted:
| |
Running ng serve will launch the app with its initial scaffolding.

Executing ng build --prod displays the list of generated files.

Notice two versions of each file: one for legacy browsers, and another compiled for ES2015, leveraging newer APIs and requiring fewer polyfills.
A significant enhancement in Angular 9 is bundle size reduction. The Angular team reports up to 40% reduction for large applications.
While bundle sizes for newly created apps are comparable to Angular 8, you’ll observe significant reductions as your application scales compared to previous versions.
Another new feature is the ability to receive warnings when a component’s style CSS file exceeds a specified size threshold.

This helps identify problematic style imports or excessively large component style files.
Building a TV Show Rating Form
Let’s add a form for rating TV shows. First, install bootstrap and ng-bootstrap:
| |
Angular 9 improves internationalization (i18n). Previously, building for each locale was necessary. Now, a single build generates all i18n files post-build, significantly reducing build times. Since ng-bootstrap relies on i18n, add the new package:
| |
Next, include the Bootstrap theme in your app’s styles.scss:
| |
Import NgbModule and ReactiveFormsModule in AppModule within app.module.ts:
| |
Update app.component.html with a basic grid for our form:
| |
Generate the form component:
| |
Add the form to rate TV shows in tv-rating-form.component.html:
| |
And define tv-rating-form.component.ts like so:
| |
Finally, incorporate the form into app.component.html:
| |
We now have basic UI functionality. Running ng serve again demonstrates this.

Before proceeding, let’s examine some valuable new debugging features introduced in Angular 9, aiming to simplify this common development task.
Debugging with Angular 9 Ivy
Angular 9 and Angular Ivy bring significant improvements to debugging. The compiler now detects more errors and presents them more clearly.
Let’s observe this firsthand. Activate template checking in tsconfig.json:
| |
Now, update the tvShows array, renaming name to title:
| |
…and the compiler will flag an error.

This type checking helps prevent typos and incorrect usage of TypeScript types.
Angular Ivy Validation for @Input()
Enhanced validation is also present for @Input(). For instance, add this to tv-rating-form.component.ts:
| |
…bind it in app.component.html:
| |
…and modify app.component.ts as follows:
| |
These changes will trigger another compiler error.

While you could use $any() in the template to cast the value to any and suppress the error:
| |
…the correct approach is to make title nullable in the form:
| |
Tackling ExpressionChangedAfterItHasBeenCheckedError in Angular 9 Ivy
Ivy provides clearer output for the dreaded ExpressionChangedAfterItHasBeenCheckedError, simplifying the process of locating the source of the problem.
Let’s intentionally trigger this error. Generate a service:
| |
Add a BehaviorSubject and methods to access the Observable and emit new values.
| |
Include this in app.component.html:
| |
In app.component.ts, inject the TitleService:
| |
Finally, in tv-rating-form.component.ts, inject TitleService and update the title of the AppComponent, which will throw an ExpressionChangedAfterItHasBeenCheckedError error.
| |
The browser’s developer console now displays a detailed error message, and clicking on app.component.html pinpoints the error’s location.

Resolve this error by wrapping the service call in setTimeout:
| |
For a deeper understanding of the ExpressionChangedAfterItHasBeenCheckedError and potential solutions, this Maxim Koretskyi’s post provides valuable insights.
Angular Ivy presents errors more clearly and enforces TypeScript typing rigorously. Next, let’s explore common scenarios where Ivy and enhanced debugging come in handy.
Writing Tests with Component Harnesses in Angular 9
Angular 9 introduces component harnesses, a new testing API designed to simplify DOM interaction, resulting in more straightforward and reliable tests.
The component harness API is part of the @angular/cdk library. Install it:
| |
Now, let’s write a test using component harnesses. In tv-rating-form.component.spec.ts, set up the test:
| |
Implement a ComponentHarness for our component. We’ll create two harnesses: one for TvRatingForm and another for NgbRating. ComponentHarness requires a static hostSelector field containing the component’s selector.
| |
For TvRatingFormHarness, create a selector for the submit button and a function to simulate a click event. Notice the improved simplicity.
| |
Next, add methods to set a rating. Here, locatorForAll finds all <span> elements representing the clickable rating stars. The rate function retrieves all rating stars and clicks the one corresponding to the provided value.
| |
Finally, connect TvRatingFormHarness to NgbRatingHarness by adding the locator to the TvRatingFormHarness class.
| |
Now, write the test:
| |
We haven’t implemented setting the select element’s value via a harness because the API doesn’t yet support option selection. This provides an opportunity to compare how element interaction worked before component harnesses.
Before running the tests, fix app.component.spec.ts since we made title nullable.
| |
Running ng test now passes the test.

Saving Data to a Database in Our Angular 9 App
Let’s conclude our Angular 9 tutorial by connecting to Firestore to save ratings.
First, create a Firebase Project. Then, install the necessary dependencies:
| |
Retrieve the Firebase project configuration from the Firebase Console’s project settings and add it to environment.ts and environment.prod.ts:
| |
Import the required modules in app.module.ts:
| |
In tv-rating-form.component.ts, inject the AngularFirestore service and save new ratings on form submission:
| |

The Firebase Console will now display the newly created item.

Lastly, list all ratings in AppComponent. In app.component.ts, retrieve the data from the collection:
| |
…and display them in app.component.html:
| |
This is the completed Angular 9 tutorial app.

Angular 9 and Angular Ivy: Enhanced Development, Improved Applications, and Seamless Compatibility
This Angular 9 tutorial covered building a basic form, saving data to Firebase, and retrieving data from it.
Along the way, we explored the improvements and new features introduced in Angular 9 and Angular Ivy. For a comprehensive list, refer to the official Angular blog’s latest release post.

Toptal, a Google Cloud Partner, offers on-demand access to Google-certified experts for your most critical projects.