brewdigital-requests v0.0.14
Brew Requests Angular
A request system for Angular
Install
npm install brewdigital-requests
oryarn add brewdigital-requests
Getting Started
First import the BrewRequestsModule into a one of your apps modules.
You will also need to import RouterModule and HttpClientModule from Angular.
import { NgModule } from '@angular/core';
import {HttpClientModule} from '@angular/common/http';
import {RouterModule} from '@angular/router';
import {BrewRequestsModule} from 'brewdigital-requests';
@NgModule({
// ...
imports: [
// ...
HttpClientModule,
RouterModule,
BrewRequestsModule
],
// ...
})
export class AppModule {}Setting Base API URL
Then add a base route for the API. This will be prepended to API requests unless withApiUrl is set to false (see below for more on this).
import { NgModule } from '@angular/core';
import {BrewRequestsModule} from 'brewdigital-requests';
@NgModule({
// ...
providers: [
{provide: 'apiUrl', useValue: 'https://jsonplaceholder.typicode.com'},
],
// ...
})
export class AppModule {}Making Requests
To make a single request in a component you can use a standalone request by providing one of the following services.
- GetRequestService
- PostRequestService
- PutRequestService
- DeleteRequestService
- FileRequestService
GetRequestService example
import {Component, OnInit} from '@angular/core';
import {GetRequestService} from 'brewdigital-requests';
@Component({
selector: 'app-get-request',
providers: [
GetRequestService,
]
})
export class GetRequestComponent implements OnInit {
constructor(
private getRequest: GetRequestService,
) {}
ngOnInit(): void {
this.getRequest.fetch('/posts').subscribe(res => console.log(res));
}
}Passing Parameters and Values
Params
The requests fetch method accepts and args parameter that can be used to pass params and values to the request.
For example passing a params object with {with: 'comments'} will append ?with=comments to the url.
GetRequestService with params example
this.getRequest.fetch('/posts', {params: {with: 'comments'}})
.subscribe(res => console.log(res));Values
Post and Put requests require a values key to be passed to the args parameter. Values will be posted in the body of the request as JSON
PostRequestService with values example
this.postRequest.fetch('/posts', {values: {title: 'A great post', body: 'The body of the post'}})
.subscribe(res => console.log(res));PutRequestService with values example
this.putRequest.fetch('/posts/1', {values: {title: 'A post', body: 'New body for the post'}})
.subscribe(res => console.log(res));Response Transforms
Before the response is sent back to the component the response status code is checked and the data is transformed to a consistent data type by a transformer.
By default success and error responses are handled using the SuccessResponseTransformer and ErrorResponseTransformer respectively.
If the request is successful the data will return with a type of responseType.SUCCESS
If the request returns an error the status code will be checked and the type will be set to one of the following error types
- responseType.ERROR
- responseType.SERVER_ERROR
- responseType.INVALID
- responseType.AUTHORISATION_FAILED
- responseType.UNAUTHORISED
- responseType.NOT_FOUND
These can be handled in the subscribe using a switch statement.
GetRequestService date example
import {Component, OnInit} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {GetRequestService, responseType} from 'brewdigital-requests';
@Component({
selector: 'app-get-request',
template: `
<div>
<div class="post">
<h1>{{post.title}}</h1>
<h1>{{post.body}}</h1>
</div>
</div>
`,
providers: [
GetRequestService,
]
})
export class GetRequestComponent implements OnInit {
private _post$ = new BehaviorSubject({
title: '',
body: ''
});
get post() {
return this._post$.value;
}
constructor(
private getRequest: GetRequestService,
) {}
ngOnInit(): void {
this.getRequest.fetch('/posts/1')
.subscribe(res => {
switch(res.type) {
case responseType.SUCCESS:
this._post$.next(res.data);
break;
case responseType.UNAUTHORISED:
// Handle Unauthorised
console.log('You are not authorised to request this data');
break;
case responseType.NOT_FOUND:
// Handle Not Found
console.log('The data requested does not exist');
break;
default:
console.log('Handle Error')
}
});
}
}Is Loading Observable
When requests are sent an isLoading observable is set to true. Components can use this to display loaders and disable inputs, or whatever else they might want to do while a request is being resolved.
GetRequestService isLoading example
import {Component, OnInit} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {GetRequestService, responseType} from 'brewdigital-requests';
@Component({
selector: 'app-get-request',
template: `
<div>
<p *ngIf="getRequest.isLoading">Loading...</p>
<div class="post" *ngIf="!getRequest.isLoading">
<h1>{{post.title}}</h1>
<p>{{post.body}}</p>
</div>
</div>
`,
providers: [
GetRequestService,
]
})
export class GetRequestComponent implements OnInit {
private _post$ = new BehaviorSubject({
title: '',
body: ''
});
get post() {
return this._post$.value;
}
constructor(
private getRequest: GetRequestService,
) {}
ngOnInit(): void {
this.getRequest.fetch('/posts/1')
.subscribe(res => {
switch(res.type) {
case responseType.SUCCESS:
this._post$.next(res.data);
break;
default:
console.log('Handle Error')
}
});
}
}withApiUrl Argument
If you want to use URL other than the apiUrl provided in root, you can set the withApiUrl argument to false and pass a full url to the fetch method.
this.getRequest.fetch('http://localhost/api/an-endpoint', {withApiUrl: false})Request Collection
If you need to make a number of requests within the same component use the RequestCollectionService.
This is just a wrapper around the instantiation of request services.
The first parameter passed to the request get, post, put, delete or file method is an id that can be used to look up the request in the collection.
RequestCollectionService example
import {Component, OnInit} from '@angular/core';
import {RequestCollectionService} from 'brewdigital-requests';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
providers: [
RequestCollectionService,
]
})
export class AppComponent implements OnInit {
constructor(
private request: RequestCollectionService,
) {}
ngOnInit(): void {
this.request.get('get_todo', '/todos/1').subscribe(res => console.log(res));
this.request.post('post_todo', '/todos', {values: {title: 'hello', completed: false}}).subscribe(res => console.log(res));
this.request.put('put_todo', '/todos/1', {values: {title: 'hello', completed: true}}).subscribe(res => console.log(res));
this.request.delete('delete_todo', '/todos/1').subscribe(res => console.log(res));
}
}RequestCollectionService getIsLoadingById
import {Component, OnInit} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {RequestCollectionService} from 'brewdigital-requests';
@Component({
selector: 'app-root',
template: `
<div>
<p *ngIf="request.getIsLoadingById('get_todo')">Loading...</p>
<div class="todo" *ngIf="!request.getIsLoadingById('get_todo')">
<h1>{{todo.title}}</h1>
<p>{{todo.completed ? 'Done' : 'Not Done'}}</p>
</div>
</div>
`,
providers: [
RequestCollectionService,
]
})
export class AppComponent implements OnInit {
private _todo$ = new BehaviorSubject({
title: '',
completed: false
});
get todo() {
return this._todo$.value;
}
constructor(
private request: RequestCollectionService,
) {}
ngOnInit(): void {
this.request.get('get_todo', '/todos/1')
.subscribe(res => console.log(res));
this.request.post('post_todo', '/todos', {values: {title: 'hello', completed: false}})
.subscribe(res => console.log(res));
this.request.put('put_todo', '/todos/1', {values: {title: 'hello', completed: true}})
.subscribe(res => console.log(res));
this.request.delete('delete_todo', '/todos/1')
.subscribe(res => console.log(res));
}
}