Skip to content
  • iImagine
  • Register
  • Log In

Web Development School

Learning made easy.

  • Books
    • Beginning Web Development with ASP.Net Core & Client-Side Technologies
      • TOC
      • Part 1
        • Chapter 1: Static HTML – Designing the landing page
      • Part 2
        • Chapter 2: ASP.Net Core – Let’s talk Dynamic
        • Chapter 3: Introduction to ASP.Net Core MVC
          [ASP.Net Core v9]
      • Part 4
        • Chapter 7: Using Server Side & Client Side technologies together
          [ASP.Net Core v7 & Angular 15]
  • Environment Setup
    • Installing Angular
    • Installing Visual Studio 2022
    • Installing SQL Server 2022 Express
    • Installing Postman
    • Installing Git for Windows
  • Blog
  • iImagine WebSolutions
  • Events
  • Learning Videos
  • Toggle search form

Vehicles Angular Component: Consuming Data

In the last module we prepared a web service to deliver just enough data for us to get started developing our Vehicles Angular Component. So let’s do it!

Tip: At this point it might be wise to copy over the project from the Module09 folder to a Module10 folder. So if the you make a mistake, you can try again. The pathway I am using for development here is:
C:\Development\FredsCars\FullStack\Module10.
You are free to use a source control system like GIT but this chapter is about ASP.Net Core/Angular full-stack development so this is another alternative to backing up your project at certain points in the development process.
If you are interested in using Git, see my article on Installing Git for Windows to get started:
https://webdevschool.iimagine-websolutions.com/environment-setup/installing-git

Table Of Contents
  1. Create the Component
  2. Load the Component
  3. Make the call: The HttpClient Service
    • Create the Interface
    • Modify the component
    • Modify the View
    • Create a proxy rule
  4. Create a generic proxy rule
  5. API URLs by Environment
    • Environment configuration settings
  6. Using a lifecycle hook: ngOnit()
  7. What's Next

Create the Component

Open up a PowerShell or command prompt and navigate to the FredsCars Angular project and run the following command.

ng generate component Vehicles --dry-run

The ng generate component command above will create a component named Vehicles. The --dry-run switch will keep the command from actually executing but still show us the modifications that would be made without the switch. So no modifications have been made to the application yet.

We can see in the image above of the command line that the ng command would have created a vehicles folder under the src/app folder and in the new vehicles folder it would have created four files. It also would have modified AppModule by registering our new component.

We are very familiar with three of the four would be new files.

*vehciles.component.ts is the TypeScript file of the component. We can think of this as the controller in an MVC software development pattern.
*vehicles.component.html is the HTML Template of the component. We can think of this as the view in an MVC software development pattern.
*vehicles.component.css is of course where we can store CSS styling specific to this component.
*vehicles.component.spec.ts is a new file type for us. “spec.ts” files are where we can write unit tests for our components.

Let’s forgo the unit testing for right now and take another dry run to look at another switch that can help.

Run the following command.

ng generate component Vehicles --skip-tests --dry-run

This is the same command we ran a moment ago but adds in the --skip-tests switch. This switch will prevent the command from generating a “spec.ts” file for the component. The resulting output can be seen below.

The output shown above is basically the same as the previous results but this time there is no “spec.ts” file. I think we have the ng command where we want it. Up until now the output results have shown a message in yellow saying that the dry run option means no changes were made. Let’s actually run it for real this time and create the component. Run the following command.

ng generate component Vehicles --skip-tests

In the command above we are removing the --dry-run switch but keeping --skip-tests. The output results are shown below.

And the component is successfully created without a test file and registered in the root module, AppModule.

We can verify this in Solution Explorer.

We can see in the screenshot above that a new vehicles folder was created under the src/app directory and the three component files were added to it. And, that the component was registered in AppModule in the app.module.ts file with the import statement at the top and adding the component to the NgModule declarations section.

Load the Component

Well we’ve created the component and we have all the files it needs living in its own directory. But how do we use it?

Let’s make the Vehicles component the main component that shows when the application starts up instead of WeatherForecast.

In the FredsCars project modify the “src\app\app.component.ts” file to contain the code below.

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

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

In the code above we just removed the WeatherForecast interface and within the component constructor we removed the WeatherForecast HTTP Get call and the public forecasts variable that used to end up holding the WeatherForecast array.

In the FredsCars project modify the “src\app\app.component.html” file to contain the code below.

<app-vehicles></app-vehicles>

That’s all we should need. Run the application in debug mode and you should see the results below.

In the browser results above you see the simple message, “vehicles works!”. This is the HTML generated by the ng generate component command.

Let’s think about what we actually did here. AppComponent is still our root component and it’s selector property within its Component decorator is app-root.

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

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

And, remember index.html in the src directory is the html file served up when the application starts and it contains an <app-root> element in its body.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>FredsCars</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

AppComponent looks for any <app-root> element and loads itself into it anytime it sees one. And it does see one in index.html and so it loads itself there.

Next the same process happens for the Vehicles component.

It’s selector is “app-vehicles”.

FredsCars/src/app/vehicles/vehicles.component.ts

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

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

It looks for any <app-vehicles> element and finds one in AppComponent’s html since it is loaded up.

<app-vehicles></app-vehicles>

And once the Vehicles component is itself loaded up, it displays it’s own html.

<p>vehicles works!</p>

Now that we have the Vehicles component in place we can make a call to the Vehicles API Get service and display some results.

Make the call: The HttpClient Service

Before making the HTTP Get request, let’s take a moment and create a strongly typed interface to store the results from that request so we won’t have to fiddle around with raw JSON results.

Create the Interface

Create a TypeScript file called vehicle.ts in the source/app/vehicles folder of the FredsCars project and fill it with the contents below.

export interface Vehicle {
  id: number;
  status: string;
  year: string;
  make: string;
  model: string;
  color: string;
  price: number;
  vin: string;
  vehicleType: string;
}

We are taking the same approach here that the Standalone TypeScript Angular project template took with WeatherForecast except we are breaking our interface out from vehicle.component.ts into its own file. Interfaces should arguably have their own files in both C# and TypeScript.

Modify the component

Next make the following modifications to vehicle.component.ts.

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Vehicle } from './vehicle';

@Component({
  selector: 'app-vehicles',
  templateUrl: './vehicles.component.html',
  styleUrls: ['./vehicles.component.css']
})
export class VehiclesComponent {
  public vehicles?: Vehicle[];

  constructor(http: HttpClient) {
    http.get<Vehicle[]>('api/vehicles').subscribe(result => {
      this.vehicles = result;
    }, error => console.error(error));
  }
}

In the code above we add in two import statements at the top of the file; The HttpClient service and our Vehicle interface.

Within the VehiclesComponent class we first declare a public nullable variable called vehicles of type Vehicle array.

public vehicles?: Vehicle[];

This is where we will store the results of the http.get request.

Next we create a class constructor which receives an instance of the HttpClient service as a parameter variable called http via DI (Dependancy Injection).

Inside of the constructor the HttpClient service is used to make an HTTP Get request to the vehicles API service.

This returns an observable which we subscribe to. The subscribe method receives the result as a JSON formatted vehicle array where each vehicle in that array should match our Vehicle interface and passes it to a function that will set the component’s vehicles property to the result.

Modify the View

Modify the vehicles.component.html with following code.

<h1>Vehicles</h1>

<p *ngIf="!vehicles"><em>Loading...</em></p>

<table *ngIf="vehicles">
  <thead>
    <tr>
      <th>Status</th>
      <th>Year</th>
      <th>Make</th>
      <th>Model</th>
      <th>Color</th>
      <th>Price</th>
      <th>Vin</th>
      <th>Category</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let vehicle of vehicles">
      <td>{{ vehicle.status }}</td>
      <td>{{ vehicle.year }}</td>
      <td>{{ vehicle.make }}</td>
      <td>{{ vehicle.model }}</td>
      <td>{{ vehicle.color }}</td>
      <td>{{ vehicle.price }}</td>
      <td>{{ vehicle.vin }}</td>
      <td>{{ vehicle.vehicleType }}</td>
    </tr>
  </tbody>
</table>

The above HTML and TypeScript/JavaScript is the same basic pattern that the WeatherForecast component used.

We have a <p> element with a structural ngIf directive that lays out a loading… message if the vehicles property is still null and thus hasn’t been loaded yet.

Next we have a <table> element with an ngIf directive that will render once the http.get call is complete and the vehicles property is no longer null or empty.

We lay out <th> table header cells in the header of the table to match our Vehicle interface properties.

In the body section of the table we have a <tr> element with an ngFor structural directive making the <tr> element a template for which each vehicle in the results of the http.get call will lay out its value for each Vehicle interface property in a <td> element.

We are just testing that we can use and render each value at this point. Eventually we won’t want every property in the main table. This should just be a general overview of each vehicle. Later in this chapter we will create a details component to show all of the complete information for a vehicle. We also don’t need to show the user the vehicle Id which will eventually come from a database. We will assume we can render this if we can render the rest of the values and we can see the Id through Swagger or Postman.

At this point if you run the application in debug mode you’ll see a 404 Not Found message for the vehicles api call in the console tab of the web development tools window. You can get to the web development tools by pressing F12 on your keyboard.

Hmm… Why is this happening?

Well if we look back in proxy.config.js in the src directory we see that we only have one rule set up for WeatherForecast. Let’s create one for Vehicles.

Create a proxy rule

Modify proxy.config.js with the following code.

const PROXY_CONFIG = [
  {
    context: [
      "/weatherforecast",
    ],
    target: "https://localhost:40443",
    secure: false
  },
  {
    context: [
      "/api/vehicles",
    ],
    target: "https://localhost:40443",
    secure: false
  }
]

module.exports = PROXY_CONFIG;

The new rule in the proxy server configuration will now let our application find the vehicles api address:

https://localhost:40443/api/vehicles

So our http.get call’s url parameter will be easily translated to the above URL.

http.get<Vehicle[]>('api/vehicles').subscribe(result => {
      this.vehicles = result

And finally if you run the application in debug mode you should see the results of all our hard work. (You may have to stop the Angular Development console window by typing Ctrl-C and then re-run the application in debug mode for the configuration change to take affect.)

Create a generic proxy rule

So now that we added the Vehicles proxy rule, we can see that we would have to create a new rule for every API controller we set up. That would be a bit of a pain. Let’s make this a little more generic. Modify proxy.config.js with the following code below.

const PROXY_CONFIG = [
  {
    context: [
      "/api",
    ],
    target: "https://localhost:40443",
    secure: false
  }
]

module.exports = PROXY_CONFIG;

In the code above we have replaced the vehicles and weatherForecasts rules with a single generic one. Now any http.get(url) call within a component with a URL param starting with “/api” will know to target https://localhost:40443/api.

If you run the application with the new configuration you should still get the same results as before where the vehcile component displays the results of our mock data in an HTML table.

API URLs by Environment

As long as we are running in development our API URLs will work. But the host in the URL we are currently using is localhost with our fixed port for development: 40443. Once in production we don’t know what the URL will be for our APIs or even if they will be on the same server as the Angular application. We need a way to specify configuration settings based on environment. There is a way and that is what we will conquer next.

Environment configuration settings

Open a command line and navigate to the FredsCars project using the following command.

C:\> cd C:\Development\FredsCars\FullStack\Module10/FredsCars

Next run the ng generate environments command from the command prompt.

ng generate environments

In the screenshot above you can see that the ng generate environments command created a folder called environments in the src folder and within the new environments folder created two new files; environment.ts and environment.development.ts.

You can also see this in Solution Explorer within Visual Studio.

Next open the environment.development.ts file and modify its contents with the following code.

FredsCars\src\environments\environment.development.ts

export const environment = {
  production: false,
  baseUrl: "/"
}

The environment.development.ts file provides configuration settings for the development environment in Angular in the same way appsettings.Development.json does for DotNet. We will be able to use this baseUrl configuration setting in any http.get() url as long as we are running in development.

Now open the environment.ts file and modify its contents with the following code.

export const environment = {
  production: true,
  baseUrl: "https://localhost:40443"
}

The environment.ts file provides configuration settings for the production environment (the default environment in Angular) in the same way appsettings.Production.json does for DotNet. We will be able to use the baseUrl configuration setting from this file in any http.get() url once we deploy to production. The baseUrl value here is just a placeholder and will likely change to a server like IIS hosting our APIs or a URL pointing to a database cloud server like Azure.

Next modify vehicles.component.ts with following code.

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Vehicle } from './vehicle';
import { environment } from '../../environments/environment';

@Component({
  selector: 'app-vehicles',
  templateUrl: './vehicles.component.html',
  styleUrls: ['./vehicles.component.css']
})
export class VehiclesComponent {
  public vehicles?: Vehicle[];

  constructor(http: HttpClient) {
    // http.get<Vehicle[]>('api/vehicles').subscribe(result => {
    http.get<Vehicle[]>(environment.baseUrl + 'api/vehicles').subscribe(result => {
      this.vehicles = result;
    }, error => console.error(error));
  }
}

In the code above we just imported the new development configuration settings file, environments.ts, in the top imports section and used its baseUrl property to concatenate a URL for the http.get url parameter.

environment.baseUrl + 'api/vehicles'

Since environment.baseUrl evaluates to ‘/’, the expression above evaluates to:

'/api/vehicles'

And from there our development proxy server configuration will evaluate that to:

https://localhost:40443/api/vehicles

Give it a whirl. Restart the application and it should still run as before with no changes to the results.

Tip: You can find more information on environment configuration here: https://angular.io/guide/build.

Using a lifecycle hook: ngOnit()

A lot of development frameworks have a Life Cycle where you can intercept key events and triggers in an application or a component and respond with some kind of response such as a callback function. And Angular is no different. Angular has a Component Lifecycle for Components and a similar Directive LifeCycle for Directives.

If we once again take a closer look at the vehicles.component.ts file in the FredsCars/src/app/vehicles folder, we see that the whole http.get() call and the subscribe() method’s function to set and initialize our public vehicles property is in the component’s constructor. Is this really the best place for it? To answer this question let’s take a look at Angular’s documentation to Initialize a component or directive.

It states:

Components should be cheap and safe to construct. You should not, for example, fetch data in a component constructor. You shouldn’t worry that a new component will try to contact a remote server when created under test or before you decide to display it.
An ngOnInit() is a good place for a component to fetch its initial data.

Perform complex initializations outside of the constructor.

It also states:

Constructors should do no more than set the initial local variables to simple values.
Keep in mind that a directive’s data-bound input properties are not set until after construction. If you need to initialize the directive based on those properties, set them when ngOnInit() runs.

Set up the component after Angular sets the input properties

If we apply the above suggestions for initializing a component to our Vehicles component, we should not fetch data to set our vehicles local variable to a Vehicle array or Vehicle[] inside the constructor. But that’s exactly what we are doing. We should move this initialization task to ngOnit(). So let’s do that. Modify the vehicles.component.ts file with the contents below.

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Vehicle } from './vehicle';
import { environment } from '../../environments/environment';

@Component({
  selector: 'app-vehicles',
  templateUrl: './vehicles.component.html',
  styleUrls: ['./vehicles.component.css']
})
export class VehiclesComponent implements OnInit {
  public vehicles?: Vehicle[];

  constructor(private http: HttpClient) {
  }

  ngOnInit() {
    this.http.get<Vehicle[]>(environment.baseUrl + 'api/vehicles').subscribe(result => {
      this.vehicles = result;
    }, error => console.error(error));
  }
}

If you restart the application and run in debug mode, then navigate to the Vehicles component, you should see the same results. The mocked vehicle data being displayed in the HTML template.

Let’s take a look at the minor changes in the above code shown in bold and blue.

First we have declared the VehiclesComponent class to implement an interface called OnInit.

export class VehiclesComponent implements OnInit {

To implement the OnInit interface, we must include a method called ngOnInit(). And this is the exact LifeCycle hook we want! But let’s take a quick look at the constructor before we inspect ngOnInit().

The constructor body is now empty because we moved the http.get() call to ngOnInit(). But we marked the http service parameter with a scope of private. This now makes the http parameter a variable available to the whole class rather then just the constructor including ngOnInit().

constructor(private http: HttpClient) {
}

After the constructor we have the new ngOnInit() method implementing the lifecycle hook.

ngOnInit() {
    this.http.get<Vehicle[]>(environment.baseUrl + 'api/vehicles').subscribe(result => {
      this.vehicles = result;
    }, error => console.error(error));
  }

Nothing new here. This is the same http call we had in the constructor except we have prefixed the http service variable with the this keyword. The this keyword lets us access the newly class scoped http variable from outside of the constructor where it is received via DI.

What’s Next

We covered a lot of ground here in this module. The results still look pretty plain and the html table definately needs more space between column cells. We will address these issues as we go. But for now we will look at routing next and create a second component for a Welcome page and discover how to navigate between multiple components.

< Prev
Next >

Leave a ReplyCancel reply

Chapter 1: Static HTML – Designing the landing page.

  • Static HTML – Designing the landing page.
  • Let’s get started!
  • Mock your site with HTML
  • Make CSS easy with Bootstrap
  • Mock your content
  • Introducing JavaScript
  • JavaScript Code Improvements
  • Results Data
  • Images and the HTML Image Element.
  • Revisiting Reusability for CSS and JavaScript
  • Reuse for HTML: PART 1
  • Reuse for HTML: PART 2
  • Details Page – Using a Bootstrap Component
  • Creating Links
  • Chapter One Conclusion

Chapter 2: ASP.Net Core – Let’s talk Dynamic

  • Introduction to ASP.Net Core
  • What is .Net?
  • What is ASP.Net
  • Introduction to Entity Framework Core

Chapter 3: ASP.Net MVC Core – Models, Views, and Controllers [ASP.Net Core v9]

  • Introduction to ASP.Net Core MVC
  • Create the project: ASP.Net Core MVC
  • Explore the ASP.Net Core Empty Web Project Template
  • Configure the Application for MVC
  • Create a Controller: Home Controller
  • Create a View: Index View for the Home Controller
  • Install Bootstrap using Libman
  • Create the Layout template
  • Create the Model
  • Install EF Core & Create the Database
  • Seed the Database: Loading test data
  • DI (Dependency Injection): Display a List of Vehicles
  • Repository Pattern: The Vehicles Repo
  • Unit Test 1: Home Controller Can Use Vehicle Repository
  • Unit Test 2: Vehicle Repository Can Return List
  • Add the ImagePath Migration and Thumbnail images to results
  • Pagination: Create a Custom Tag Helper
  • Sorting
  • Category Filter
  • Partial View: Break out the vehicle results
  • View Component: Create dynamic category buttons
  • Create the Details page
  • Create the Create Page

Chapter 7: Using Server Side & Client Side technologies together. [ASP.Net Core v7 & Angular v15]

  • Intro to Full Stack Development
  • Fred’s Cars – Full Stack Development
  • Prepare the environment
  • Create the Visual Studio Solution
  • Add the ASP.Net Core Web API project
  • Add the Angular Project
  • Wire it up!
  • WeatherForecast: Understanding the basics
  • Vehicles API Controller: Mock Data
  • Vehicles Angular Component: Consuming Data
  • Routing and Navigation
  • Using a Component Library: Angular Material
  • Our first Angular Material Component: MatToolbar
  • Configuring for Saas: CSS with superpowers
  • Create the Header & Footer components
  • Displaying Results with MatTable
  • Loading: Using a Progress Spinner
  • MatTable: Client-Side Paging and Sorting
  • MatSidenav: Create a Search Sidebar
  • MatCheckbox: Category Search UI
  • Adding an image to the welcome page
  • Create the database with Entity Framework Core migrations
  • MatPaginator & PageEvent: Custom Server-Side Paging
  • Unit Testing: Custom Server-Side Paging
  • Repository Pattern: VehicleRepository
  • Unit Test: Paging in the Vehicles controller
  • Server-Side Sorting
  • Unit Tests: Sorting
  • Filter (Quick Search)
  • Unit Tests: Filter feature
  • Advanced Search: Categories
  • Unit Tests: Search by category
  • Progress Spinner: Final Fix

TOC

  • What were WebForms?
  • Enter MVC
    • Understanding MVC
    • Advantages of MVC
  • ASP.Net Core MVC – A total rewrite
  • ASP.Net Core 2 MVC – Here come Razor Pages
    • Understanding Razor Pages
  • ASP.Net Core 3 – Dropping the MVC reference
    • Understanding Blazor
  • Dropping the MVC reference
  • Hello .Net 5!
  • What’s Next? – Here comes .Net 6.

Recent Posts

  • Angular Commands Cheat Sheet
  • Installing Git for Windows
  • Installing Postman
  • Installing SQL Server 2022 Express
  • Installing Visual Studio 2022

Recent Comments

No comments to show.

Archives

  • November 2023
  • October 2023
  • June 2023
  • October 2021

Categories

  • Angular
  • ASP.Net
  • Environment Setup
  • See All
  • SQL Server
  • Visual Studio
  • Web API & Rest Services

WordPress Theme Editor

Copyright © 2025 Web Development School.

Powered by PressBook Blog WordPress theme