Updated on

Angular project preparation can vary from project to project and from version to version, and this article is dedicated to that topic.

Creating the server part (.NET Core Web API part) is just half of the job we want to accomplish. From this point onwards, we are going to dive into the client side of the application to consume the Web API part and show the results to the user by using angular components and many other features.

This part picks up where POST, PUT, and DELETE in ASP.NET Core Web API left off. The API is finished, and from here on we build the client that consumes it.

For complete navigation and all the basic instructions of the Angular series, check out: Introduction of the Angular series.

So, let’s start.

To download the source code for this article, you can visit the AngularProjectSetup folder in our GitHub repository. The source code for the whole Angular series is here.
The Web API this client is written against is the finished back end from the first half of the series: the UsingRepositoryForWriteRequests folder in our GitHub repository. This part sends no requests, so there is nothing to start yet.

Installation of the Angular CLI and Starting a New Project

First, we are going to install the Angular CLI (Angular Command Line Interface) which will help us a lot with the Angular project preparation and Angular project development overall.

To install Angular CLI, we need to open the command prompt (the best option is to open it as administrator) and use the install command:

npm install -g @angular/cli

If you already have the Angular CLI installed, you can check if you have the latest version:

ng --version

If you don’t have the latest version (22 at the time of writing), you can uninstall it:

npm uninstall -g @angular/cli
npm cache clean --force

And after that, we can use the install command (mentioned above) to reinstall it.

After the installation completes, we are going to create a new project in the same command window:

ng new AccountOwnerClient

Two questions will appear. The first one asks which stylesheet system we want, and we answer CSS (just hit enter). The second one asks whether we want Server-Side Rendering, and we answer No. Routing is not one of the questions any more, because the CLI adds it to every new project.

It will take some time to create the project.

An application generated on Angular 22 runs without zone.js, and its components use the OnPush change detection strategy unless they say otherwise. This series keeps both defaults. The one thing to know about them now is that data which arrives after a request is held in a signal, which we come to when we build the owner list in part 10.

After the creation process is over, we are going to open the project folder inside our editor. We will use Visual Studio Code.

Third-Party Libraries as Part Of Angular Project Preparation

We are going to use the ngx-bootstrap library (angular bootstrap) for styling, so let’s install it using the terminal window in the VS Code:

ng add ngx-bootstrap

After we start the installation, it will tell us which ngx-bootstrap version it is about to install and whether we like to proceed. We are going to confirm that and finish the installation.

With this installation, we are installing both bootstrap and ngx-bootstrap, and also our package.json and angular.json files will be updated:

    ✅️ Added "bootstrap
    ✅️ Added "ngx-bootstrap
UPDATE package.json (855 bytes)
UPDATE angular.json (2082 bytes)

At this point, we can try to run our app:

ng serve -o

With this command, we are going to run our app and also open it in a browser automatically (-o flag).

After a few seconds, we are going to see the initial page:

The Angular welcome page in a browser, reading Hello, AccountOwnerClient and Congratulations! Your app is running.

The next step is adding our components to the project.

What Is an Angular Component?

An Angular component is a TypeScript class with a @Component decorator, and it owns three things: a selector, a template, and styles.

The selector is the tag we write in another template. selector: 'app-home' means that wherever <app-home></app-home> appears, this component renders.

The template is the markup. templateUrl points at a separate file, template holds the markup inline, and styles work the same way through styleUrl and styles.

The class holds the data and the methods the template binds to. A property named homeText is readable in that component’s template as {{ homeText }}, and nowhere else.

An application is a tree of these. Bootstrapping starts one root component, that component’s template names its children, and each child names its own, all the way down.

Since Angular 19, a component is standalone unless it says otherwise. It declares what its template needs in its own imports array rather than being registered in a module somewhere else in the project.

That said, let’s take a look inside the src/app/app.ts file:

import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  imports: [RouterOutlet],
  selector: 'app-root',
  styleUrl: './app.css',
  templateUrl: './app.html',
})
export class App {
  protected readonly title = signal('AccountOwnerClient');
}

Every component must import Component from the @angular/core package. We will import more things when we need them. Also, we can notice the @Component decorator inside the code.

This is the place where we create our selector (it is the same as the app-root tag in the index.html file, the single page everything else renders into). Additionally, we are binding the HTML template for this component with the templateUrl and its stylesheet with styleUrl.

The imports array is where a standalone component lists what its own template uses. The Angular components guide puts it this way: “By default, Angular components are standalone, meaning that you can directly add them to the imports array of other components”. The generated root component imports RouterOutlet because the template the CLI writes contains a <router-outlet> element.

Lastly, we have the exported class for the component.

How Do We Create a New Angular Component With the CLI?

ng generate component home creates the component and its files. ng g component home is the short form, and both do the same work.

The command writes four files into src/app/home: the class, the template, the stylesheet, and a spec file for tests. Adding --skip-tests drops the spec, which is what this series does to keep the folders small.

File names follow whatever convention the installed CLI uses. The current CLI drops the .component infix from generated names, so a component generated today lands in home.ts rather than home.component.ts. Existing projects keep the names they already have. The CLI only changes what it writes next.

Nothing else needs editing afterwards. A standalone component becomes usable by importing its class into the imports array of whichever component’s template uses it, and the CLI leaves that step alone because it cannot know where the component belongs.

Passing a path works too. ng g component error-pages/not-found nests the four files, which is how this series groups its error screens.

ng g component home --skip-tests

With this command, we create the Home component with three files (.ts, .html, .css):

CREATE src/app/home/home.ts (187 bytes)
CREATE src/app/home/home.css (0 bytes)
CREATE src/app/home/home.html (20 bytes)

Also, by adding the --skip-tests flag, we prevent creating the test file.

After the creation, we can inspect the Home component:

import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  styleUrl: './home.css',
  templateUrl: './home.html',
})
export class Home {}

The class the CLI writes has nothing in it: no constructor and no lifecycle hooks. Later parts of this series add an ngOnInit method to the components that have to fetch something once they are on screen, and Angular calls that method right after it creates the component. Dependencies do not arrive through a constructor either, because the services we build from part 9 onwards ask for them with the inject function.

Where Did app.module.ts Go in a New Angular Project?

ng new no longer creates an app.module.ts. A project generated today bootstraps a single standalone component instead, and there is no root module to open.

main.ts calls bootstrapApplication(App, appConfig). app.config.ts holds the providers that used to be application-wide, which is where the router and the HTTP client get configured in later parts of this series. app.routes.ts holds the route array.

The module’s three arrays each went somewhere different. declarations is gone outright, because a standalone component declares itself. imports moved onto each component and lists only what that component’s own template uses. providers moved into app.config.ts, or onto the service itself.

NgModule still exists and applications built on it still run. A component written before Angular 19 carries standalone: false and stays inside its module, and nothing forces an upgrade.

For new code the module is simply not part of the picture, and the rest of this series is written that way.

FileWhat it holdsWhat it replaced
src/main.tsbootstrapApplication(App, appConfig)platformBrowserDynamic() and bootstrapModule(AppModule)
src/app/app.tsThe root component class, Appapp.component.ts, class AppComponent
src/app/app.htmlThe root templateapp.component.html
src/app/app.cssThe root component's stylesapp.component.css
src/app/app.spec.tsThe root component's testapp.component.spec.ts
src/app/app.config.tsApplication-wide providersthe providers and imports arrays of AppModule
src/app/app.routes.tsThe Routes arrayapp-routing.module.ts
not generated-src/app/app.module.ts
not generated-src/environments/ (run ng generate environments)

The whole startup chain runs from one file to one component, and there is no module anywhere in it.

Angular application startup: main.ts calls bootstrapApplication with the App root component and app.config.ts providers, and App renders the Home component.

So the only wiring a new component needs is one entry in the root component’s imports array, which is what the next section does.

Additional Content in the Home Component

Let’s modify the home.ts file:

export class Home {
  public homeText = 'WELCOME TO ACCOUNT-OWNER APPLICATION';
}

Then, let’s add a new class to the home.css file:

.homeText {
  font-size: 35px;
  color: red;
  text-align: center;
  position: relative;
  top: 30px;
  text-shadow: 2px 2px 2px gray;
}

To continue, we are going to change the home.html file:

<p class="homeText">{{homeText}}</p>

Finally, let’s modify the app.html file, by removing all the content and adding a new one, just to test if this works:

<div class="container">
  <div class="row">
    <div class="col">
      <app-home></app-home>
    </div>
  </div>
</div>

A standalone component renders only what its own imports array names, so App has to import Home before <app-home> resolves to anything. The template no longer holds a <router-outlet> element either, so RouterOutlet comes out in the same edit:

import { Component, signal } from '@angular/core';

import { Home } from './home/home';

@Component({
  imports: [Home],
  selector: 'app-root',
  styleUrl: './app.css',
  templateUrl: './app.html',
})
export class App {
  protected readonly title = signal('AccountOwnerClient');
}

Now in the terminal, let’s type again ng serve -o and wait for the application to compile and run. We should see the welcome message on the screen from the Home component.

Conclusion

Right now we have a working component and an Angular application that we can run in our browser. But it is just the beginning. We have a long way ahead of us because there are still a lot of important Angular features to introduce to the project.

For a wider view of how to keep an Angular codebase in shape as it grows, we have a separate guide on Angular development best practices.

In the next part of the series, Angular Routing and Navigation Menu, we are going to create the navigation menu and configure the routing.

Tested with Angular 22.1.5, Angular CLI 22.1.7, ngx-bootstrap 22.0.0, Bootstrap 5.3.8, TypeScript 6.0.3 and Node 24.