Resource Core is an evolution of ngx-resource lib which provides freedom for the developers. Each developer can implement his own request handlers.
In fact, @ngx-resource/core
is an abstract common library which uses ResourceHandler
to make an requests, so it's even possible to use the lib on node.js server side with typescript. Just need to implement ResourceHandler
for it.
All my examples will be based on angalar 4.4.4+
@ngx-resource/handler-ngx-http
. Based onHttpClient
from@angular/common/http
. IncludesResourceModule.forRoot
.@ngx-resource/handler-ngx-http-legacy
. Based onHttp
from@angular/http
. IncludesResourceModule.forRoot
.@ngx-resource/handler-cordova-advanced-http
. Based on Cordova Plugin Advanced HTTP.@ngx-resource/handler-fetch
. Besed on Fetch API. Not yet created.
@Injectable()
@ResourceParams({
// IResourceParams
pathPrefix: '/auth'
})
export class MyAuthResource extends Resource {
@ResourceAction({
// IResourceAction
method: ResourceRequestMethod.Post,
path: '/login'
})
login: IResourceMethod<{login: string, password: string}, IReturnData>; // will make an post request to /auth/login
@ResourceAction({
// IResourceAction
//method: ResourceRequestMethod.Get is by default
path: '/logout'
})
logout: IResourceMethod<void, void>;
constructor(restHandler: ResourceHandler) {
super(restHandler);
}
}
@Injectable()
@ResourceParams({
// IResourceParams
pathPrefix: '/user'
})
export class UserResource extends Resource {
@ResourceAction({
path: '/{!id}'
})
getUser: IResourceMethod<{id: string}, IUser>; // will call /user/id
@ResourceAction({
method: ResourceRequestMethod.Post
})
createUser: IResourceMethodStrict<IUser, IUserQuery, IUserPathParams, IUser>;
constructor(restHandler: ResourceHandler) {
super(restHandler);
}
}
// Using created rest
@Injectable
export class MyService {
private user: IUser = null;
constructor(private myResource: MyAuthResource, private userResource: UserResource) {}
doLogin(login: string, password: string): Promise<any> {
return this.myResource.login({login, password});
}
doLogout(): Promise<any> {
return this.myResource.logout();
}
async loginAndLoadUser(login: string, password: string, userId: string): Promise<any> {
await this.doLogin(login, password);
this.user = await this.userResource.getUser({id: userId});
}
}
Final url is generated by concatination of $getUrl
, $getPathPrefix
and $getPath
methods of Resource
base class.
Is used by ResourceParams
decorator for class decoration
List of params:
url?: string;
- url of the api server; default''
pathPrefix?: string;
- path prefix of the api; default''
path?: string;
- path of the api; default''
headers?: any;
- headers; default{}
body?: any;
- default body; defaultnull
params?: any;
- default url params; defaultnull
query?: any;
- defualt query params; defaultnull
rootNode?: string;
- key to assign all body; defaultnull
removeTrailingSlash?: boolean;
- defaulttrue
addTimestamp?: boolean | string;
- defaultfalse
withCredentials?: boolean;
- defaultfalse
lean?: boolean;
- do no add$
properties on result. Used only withtoPromise: false
defaultfalse
mutateBody?: boolean;
- if need to mutate provided body with response body. defaultfalse
asPromise?: boolean;
- if method should return promise or object, which will be fullfilled after receiving response. defaulttrue
requestBodyType?: ResourceRequestBodyType;
- request body type. default: will be detected automatically. Check for possible body types in the sources of ResourceRequestBodyType. Type detection algorithm check here.responseBodyType?: ResourceResponseBodyType;
- response body type. default:ResourceResponseBodyType.JSON
Possible body type can be checked here ResourceResponseBodyType.
Is used by ResourceAction
decorator for methods.
List of params (is all above) plus following:
method?: ResourceRequestMethod;
- method of request. DefaultResourceRequestMethod.Get
. All possible methods listed in ResourceRequestMethodexpectJsonArray?: boolean;
- if expected to receive an array. The field is used only withtoPromise: false
. Defaultfalse
.resultFactory?: IResourceResultFactory;
- custom method to create result object. Default:returns {}
map?: IResourceResponseMap;
- custom data mapping method. Default:returns without any changes
filter?: IResourceResponseFilter;
- custom data filtering method. Default:returns true
Mainly used to set defaults
What is that. It's an object which has build in methods to save, update, delete an model.
Here is an example of User
model.
export interface IPaginationQuery {
page?: number;
perPage?: number;
}
export interface IGroupQuery extends IPaginationQuery {
title?: string;
}
export interface IUserQuery extends IPaginationQuery {
firstName?: string;
lastName?: string;
groupId?: number;
}
export interface IUser {
id: number;
userName: string;
firstName: string;
lastName: string;
groupId: string;
}
export class GroupResource extends ResourceCRUD<IGroupQuery, Group, Group> {
constructor(restHandler: ResourceHandler) {
super(restHandler);
}
$resultFactory(data: any, options: IResourceActionInner = {}): any {
return new Group(data);
}
}
export class Group extends ResourceModel {
readonly $rest = GroupResource;
id: number;
title: string;
constructor(data?: IGroup) {
super();
if (data) {
this.$setData(data);
}
}
$setData(data: IGroup) {
this.id = data.id;
this.title = data.title;
}
}
export class UserResource extends ResourceCRUD<IUserQuery, User, User> {
constructor(restHandler: ResourceHandler) {
super(restHandler);
}
$resultFactory(data: any, options: IResourceActionInner = {}): any {
return new User(data);
}
}
export class User extends ResourceModel implements IUser {
readonly $rest = UserResource;
id: number;
userName: string;
firstName: string;
lastName: string;
groupId: string;
fullName: string; // generated from first name and last name
constructor(data?: IUser) {
super();
if (data) {
this.$setData(data);
}
}
$setData(data: IUser): this {
Object.assign(data);
this.fullName = `${this.firstName} ${this.lastName}`;
return this;
}
toJSON() {
// here i'm using lodash lib pick method.
return _.pick(this, ['id', 'firstName', 'lastName', 'groupId']);
}
}
// example of using the staff
async someMethodToCreateGroupAndUser() {
// Creation a group
const group = new Group();
group.title = 'My group';
// Saving the group
await group.$save();
// Creating an user
const user = new User({
userName: 'troyanskiy',
firstName: 'firstName',
lastName: 'lastName',
groupId: group.id
});
// Saving the user
await user.$save();
}
You can define the way query params are converted Set the global config at the root of your app.
ResourceGlobalConfig.queryMappingMethod = ResourceQueryMappingMethod.<CONVERTION_STRATEGY>
{
a: [{ b:1, c: [2, 3] }]
}
With <CONVERTION_STRATEGY>
being an enumerable within
No convertion at all.
Output: ?a=[Object object]
All array elements will be indexed
Output: ?a[0][b]=10383&a[0][c][0]=2&a[0][c][1]=3
Implements the standard $.params way of converting
Output: ?a[0][b]=10383&a[0][c][]=2&a[0][c][]=3
Use ResourceHandler
abstract class as parent to create your Handler. I think it's clear what should it do by checking sources of the class.