How to make HTTP Calls in Angular

In this detailed article, let's discover how we can make HTTP API calls from Angular using HttpClient library with an example

Introduction

Single Page Applications often rely on HTTP requests for requesting data from APIs through which they operate on the data fetched into powerful presentation logic or front-end transformations.

For example, a Weather application built on a front-end technology such as Angular itself doesn’t access the backend databases or domain systems for data it shows.

Instead, it makes requests to a server-side WeatherForecast API which encapsulates the business or data logic using which it reads from the underlying database or domain systems and returns appropriate Weather data to the application, which then applies its own features and presents to the user.

We can make HTTP calls to APIs in Angular using the HttpClient library. It is a part of the @angular/common/http package.

Consider the SocialApp which displays a list of Posts created by various Users and enables one to interact with it. The core feature of this application is showing the post list, which obviously requires the application to fetch data from a remote API.

How to make HTTP API calls using HTTP Client in Angular with Example

Importing HttpClientModule in AppModule

To do this, we use the HttpClient package for working with API requests. First, We add the HttpClientModule to the list of imports in our Module class.

@NgModule({
    declarations: [
        PostItemComponent,
        PostListComponent,
        NewPostComponent
    ],
    imports: [
        // other modules to import
        HttpClientModule
    ],
})
export class PostsModule { }

Once included, we can now access the HttpClient service in all the Components and Services local to that Module.

Injecting HttpClient into Service

Next, create a service class which shall provide us with Posts related functionalities for the requesting components. This PostsService class is responsible for making HTTP request to the APIs and transforming the response data according to the components.

@Injectable({
    providedIn: "root"
})
export class PostsService {
    private posts: Post[] = [];
    private apiUri = "http://server-api-domain.com/api";


    constructor(private http: HttpClient) { }


    // --- other methods-- -


    // GET all posts
    // from the API
    getPosts(): Observable<Post[]> {
        return this.http.get<Post[]>(`${this.apiUri}/posts`)
            .pipe(map((res: Post[]) => {
                this.posts = [...res];
                // --- other logic-- -
                return res;
            }));
    }


    // GET single post
    // from the API
    getPost(id: string): Observable<Post> {
        return this.http.get<Post>(`${this.apiUri}/posts/${id}`);
    }


    // POST new post item
    // to the API
    createPost(status: string): Observable<Post> {
        let post: Post = {
            Text: status,
            Type: PostType.Status,
            Id: null,
            AssetUrl: null,
            PostedBy: Guid.create().toString(),
            PostedOn: new Date()
        };


        return this.http.post<Post>(`${this.apiUri}/posts`, post)
            .pipe(map((res) => {
                this.posts.push(res);
                // --- other logic--
                return res;
            }));
    }
}

Observe that the PostsService offers three methods which fetches ALL the posts from the database, a SINGLE post from the database and POSTs a new post item to the database.

Internal to each method is an individual API call using the HttpClient object, which is injected via the constructor.

Available methods in HttpClient for API Calls

HttpClient class provides methods to perform the four primary API operations:

  • http.get(api_url) – for GET requests to read data
  • http.post(api_url, data_object) – for POST requests to insert data
  • http.put(api_url, data_object) – for PUT requests to replace an object in the database
  • http.patch(api_url, data_object) – for PATCH requests to update one or more properties of an object in the database

Each of these methods return an Observable which contains the response content from the API.

// similarly for other methods#
var postResponse = this.http.post<Post>(`${this.apiUri}/posts`, post);
var putResponse = this.http.put<Post>(`${this.apiUri}/posts`, post);
var patchResponse = this.http.patch<Post>(`${this.apiUri}/posts`, post)
var getResponse = this.http.get<Post[]>(`${this.apiUri}/posts`);


getResponse.subscribe((posts) => {
    // posts is an array of Post objects
});

In the above code, take for example the getPosts() method which receives all post objects from the database.

To do this, we call the http.get() method with respective API endpoint. We also pass the type which we’re expecting from this API call, in our case it is an array of Post objects.

However, since we would want to pass this subscription to the calling component which can subscribe to this and receive data, we return the subscription in our getPosts() method.

However, we want to maintain a local copy of the Posts array at the service level so that we can trigger events to subscribed components for any changes in this Posts array.

For this, we want to get hold of the response from the http.get() method, and pass on the subscription once we’re done with our job. We do this using pipe and map methods.

What is a Pipe? What is a Map?

Observable provides a pipe() method which we can temporarily attach to the Observable stream and pass to the next listener after performing some operations.

Inside pipe() we use the map() which is an RxJs operator. map operator is similar to JavaScript map() method which can help us to map an incoming object into another object.

Together, we grab the HttpResponse stream which contains a Post[] content and then push the incoming response Post array into our local post array.

Finally we return the response content so that it goes on to the next listener on the Observable stream.

postResponse.pipe(map((res: Post[]) => {
    this.posts = [...res];
    // --- other logic-- -
    return res;
}));

On the component side, we subscribe to the getPosts() method on the PostsService service and once the response content is available, we assign the returned post array to our model which is dynamically bound to the view.

@Component({
    selector: 'app-post-list',
    templateUrl: './post-list.component.html',
    styleUrls: ['./post-list.component.css']
})
export class PostListComponent implements OnInit, OnDestroy {


    posts: Post[] = [];


    constructor(private postsService: PostsService, router: Router) { }


    ngOnDestroy(): void {
    }


    ngOnInit(): void {
        this.postsService.getPosts().subscribe((posts) => {
            this.posts = [...posts];
        });
    }
}

The result data is binded in the HTML template of the component as below.

<a *ngFor="let post of posts;" [routerLink]="['/posts', post?.Id]">
    <div class="card my-2">
        <div class="card-body">
            <div class="container-fluid">
                <p class="card-text">{{post?.Text}}</p>
            </div>
        </div>
    </div>
</a>

Conclusion

In this way, we can use the inbuilt HttpClient library in Angular to make HTTP API calls and subscribe to the response observables. We can also transform the response using Pipe and Map combination from Rxjs library.

The code snippets used above is a part of the OpenSocialApp repository and available in GitHub – https://github.com/referbruv/opensocialapp-angular-example

Keep in mind that a call for HTTP request using HttpClient starts only when the subscribe() method is called on the Observable the http method returns.

Each time when we call subscribe() method on the Observable stream, a new individual request is created from the client.

var obs = this.postsService.getPosts();

// original request 1
obs.subscribe(
    (posts) => {
        // original response 1
    }
);

// original request 2
obs.subscribe(
    (posts) => {
        // original response 2
    }
);

// original request 3
obs.subscribe(
    (posts) => {
        // original response 3
    }
);

Extensive features, strong community support, comprehensive documentation, and vast ecosystem of libraries and tools make Angular a valuable skill to acquire for career growth in 2023.

Check out this most popular Angular course in Udemy at a HUGE DISCOUNT for a LIMITED PERIOD – Angular – The Complete Guide (2023 Edition) exclusive for our readers!


Buy Me A Coffee

Found this article helpful? Please consider supporting!

Ram
Ram

I'm a full-stack developer and a software enthusiast who likes to play around with cloud and tech stack out of curiosity. You can connect with me on Medium, Twitter or LinkedIn.

Leave a Reply

Your email address will not be published. Required fields are marked *