Open Christian-health opened 6 years ago
Ngx-restangular almost all functionality was transferred from the Restangular. We are open to any cooperation in terms of its further development. Ngx-restangular几乎所有的功能都从Restangular转移。 我们愿意在进一步发展方面进行任何合作。
This project was renamed from ng2-restangular to ngx-restangular due to implementation of Semantic Versioning by Angular Core Team. NPM name also changed, you can install actual version of project with npm install ngx-restangular.
由于Angular Core Team的语义版本控制的实现,该项目从ng2-restangular重命名为ngx-restangular。 NPM名称也改变了,可以使用npm安装ngx-restangular安装实际版本的项目。
You can download this by: Using npm and running npm install ngx-restangular 你可以下载: 使用npm并运行npm install ngx-restangular
Restangular depends on Angular2+ and Lodash. Restangular 取决于Angular2 +和Lodash。
这就是开始使用所有基本的Restangular功能所需要的。
在app.modules.ts中需要做的事情
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { RestangularModule, Restangular } from 'ngx-restangular'; //导入Restangular相关
// Function for setting the default restangular configuration
用于设置默认restangular配置的功能
export function RestangularConfigFactory (RestangularProvider) {
RestangularProvider.setBaseUrl('http://api.restngx.local/v1');
RestangularProvider.setDefaultHeaders({'Authorization': 'Bearer UDXPx-Xko0w4BRKajozCVy20X11MRZs1'});
}
// AppModule is the main entry point into Angular2 bootstraping process
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
imports: [
// Importing RestangularModule and making default configs for restanglar
// 导入RestangularModule并为restanglar创建默认配置
RestangularModule.forRoot(RestangularConfigFactory),
]
})
export class AppModule {
}
// later in code ...
在使用restAngular的组建中所要做的事情
@Component({
...
})
export class OtherComponent {
constructor(private restangular: Restangular) { //导入restAngualr
}
ngOnInit() {
// GET http://api.test.local/v1/users/2/accounts
this.restangular.one('users', 2).all('accounts').getList(); //使用restAngular
}
Creating Main Restangular object. 创建主Restangular对象
There are 3 ways of creating a main Restangular object. The first one and most common one is by stating the main route of all requests. The second one is by stating the main route and object of all requests. 有三种创建Restangular主要对象的方法。 第一个也是最常见的一个是通过说明所有请求的主要路由。 第二个是通过说明所有请求的主要路由和对象。
// Only stating main route 只是描述主要路由 Restangular.all('accounts')
// Stating main object 描述主要对象 Restangular.one('accounts', 1234)
// Gets a list of all of those accounts
Restangular.several('accounts', 1234, 123, 12345);
Now that we have our main Object let's start playing with it. 现在我们有我们的主要Object让我们开始和它愉快的玩耍。
// AppModule is the main entry point into Angular2 bootstraping process
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
imports: [
// Importing RestangularModule
RestangularModule,
]
})
export class AppModule {
}
@Component({
...
})
export class OtherComponent {
allAccounts;
accounts;
account;
constructor(private restangular: Restangular) {
}
ngOnInit() {
// First way of creating a this.restangular object. Just saying the base URL
let baseAccounts = this.restangular.all('accounts');
// This will query /accounts and return a observable.
baseAccounts.getList().subscribe(accounts => {
this.allAccounts = accounts;
});
let newAccount = {name: "Gonto's account"};
// POST /accounts
baseAccounts.post(newAccount);
// GET to http://www.google.com/ You set the URL in this case
this.restangular.allUrl('googlers', 'http://www.google.com/').getList();
// GET to http://www.google.com/1 You set the URL in this case
this.restangular.oneUrl('googlers', 'http://www.google.com/1').get();
// You can do RequestLess "connections" if you need as well
// Just ONE GET to /accounts/123/buildings/456
this.restangular.one('accounts', 123).one('buildings', 456).get();
// Just ONE GET to /accounts/123/buildings
this.restangular.one('accounts', 123).getList('buildings');
// Here we use Observables
// GET /accounts
let baseAccounts$ = baseAccounts.getList().subscribe(accounts => {
// Here we can continue fetching the tree :).
let firstAccount = accounts[0];
// This will query /accounts/123/buildings considering 123 is the id of the firstAccount
let buildings = firstAccount.getList("buildings");
// GET /accounts/123/places?query=param with request header: x-user:mgonto
let loggedInPlaces = firstAccount.getList("places", {query: 'param'}, {'x-user': 'mgonto'});
// This is a regular JS object, we can change anything we want :)
firstAccount.name = "Gonto";
// If we wanted to keep the original as it is, we can copy it to a new element
let editFirstAccount = this.restangular.copy(firstAccount);
editFirstAccount.name = "New Name";
// PUT /accounts/123. The name of this account will be changed from now on
firstAccount.put();
editFirstAccount.put();
// PUT /accounts/123. Save will do POST or PUT accordingly
firstAccount.save();
// DELETE /accounts/123 We don't have first account anymore :(
firstAccount.remove();
}, () => {
alert("Oops error from server :(");
});
// Get first account
let firstAccount$ = baseAccounts$.map(accounts => accounts[0]);
// POST /accounts/123/buildings with MyBuilding information
firstAccount$.switchMap(firstAccount => {
var myBuilding = {
name: "Gonto's Building",
place: "Argentina"
};
return firstAccount.post("Buildings", myBuilding)
})
.subscribe(() => {
console.log("Object saved OK");
}, () => {
console.log("There was an error saving");
});
// GET /accounts/123/users?query=params
firstAccount$.switchMap(firstAccount => {
var myBuilding = {
name: "Gonto's Building",
place: "Argentina"
};
return firstAccount.getList("users", {query: 'params'});
})
.subscribe((users) => {
// Instead of posting nested element, a collection can post to itself
// POST /accounts/123/users
users.post({userName: 'unknown'});
// Custom methods are available now :).
// GET /accounts/123/users/messages?param=myParam
users.customGET("messages", {param: "myParam"});
var firstUser = users[0];
// GET /accounts/123/users/456. Just in case we want to update one user :)
let userFromServer = firstUser.get();
// ALL http methods are available :)
// HEAD /accounts/123/users/456
firstUser.head()
}, () => {
console.log("There was an error saving");
});
// Second way of creating this.restangular object. URL and ID :)
var account = this.restangular.one("accounts", 123);
// GET /accounts/123?single=true
this.account = account.get({single: true});
// POST /accounts/123/messages?param=myParam with the body of name: "My Message"
account.customPOST({name: "My Message"}, "messages", {param: "myParam"}, {})
}
}
The errorInterceptor is called whenever there's an error. It's a function that receives the response, subject and the Restangular-response handler as parameters. 每当有错误时调用errorInterceptor。 它是一个接收response,subject ,和Restangular-response处理程序函数作为参数。 The errorInterceptor function, whenever it returns false, prevents the observable linked to a Restangular request to be executed. All other return values (besides false) are ignored and the observable follows the usual path, eventually reaching the success or error hooks. errorInterceptor函数,每当返回false,都会阻止链接到Restangular请求的observable被执行。 所有其他返回值(除了false)都被忽略,并且observable遵循通常的路径,最终达到成功或错误的钩子。
The refreshAccesstoken function must return observable. It`s function that will be done before repeating the request, there you can make some actions. In switchMap you might do some transformations to request.
refreshAccesstoken函数必须返回observable。 它的功能将在重复请求之前完成,您可以进行一些操作。 在switchMap中,您可能需要进行一些转换才能请求。
// Function for settting the default restangular configuration
//用于设置默认restangular配置的功能
export function RestangularConfigFactory (RestangularProvider, authService) {
RestangularProvider.setBaseUrl('http://api.test.com/v1');
// This function must return observable
// 这个函数必须返回一个observable
var refreshAccesstoken = function () {
// Here you can make action before repeated request
// 在进行重复的请求之前,你可以在这里执行一些操作
return authService.functionForTokenUpdate();
};
RestangularProvider.addErrorInterceptor((response, subject, responseHandler) => {
if (response.status === 403) {
refreshAccesstoken()
.switchMap(refreshAccesstokenResponse => {//refreshAccesstokenResponse 获取到的新的accessToken,然后进行设置。
//If you want to change request or make with it some actions and give the request to the repeatRequest func.
//如果您想要更改请求或者做一些操作,并将请求发送到repeatRequest 函数.或者您可以将其空闲并请求将是一样的。
//Or you can live it empty and request will be the same.
//或者您可以让它为空,并请求将是一样的。
// update Authorization header 更新认证header
response.request.headers.set('Authorization', 'Bearer ' + refreshAccesstokenResponse)
return response.repeatRequest(response.request);//从新进行这个请求
})
.subscribe(
res => responseHandler(res),
err => subject.error(err)
);
return false; // error handled 错误处理
}
return true; // error not handled 错误不处理
});
}
// AppModule is the main entry point into Angular2 bootstraping process
@NgModule({
bootstrap: [ AppComponent ],
imports: [
// Importing RestangularModule and making default configs for restanglar
// 导入RestangularModule模块,并且为restangular设置默认的配置
RestangularModule.forRoot([authService], RestangularConfigFactory),
],
})
The responseInterceptor is called after we get each response from the server. It's a function that receives this arguments: 在我们从服务器获取每个响应之后调用responseInterceptor。 responseInterceptor的参数是一个函数,这个函数的参数如下:
Some of the use cases of the responseInterceptor are handling wrapped responses and enhancing response elements with more methods among others. responseInterceptor使用场景是用来用更多的方法包装响应和增强响应元素。 The responseInterceptor must return the restangularized data element.
RestangularProvider.addResponseInterceptor((data, operation, what, url, response)=> {
return data;
});
});
You can set default Headers to be sent with every request. Send format: {header_name: header_value} 您可以设置每个请求发送的默认headers。 发送格式:{header_name:header_value}
import { NgModule } from '@angular/core';
import { RestangularModule, Restangular } from 'ngx-restangular';//导入restangular
// Function for settting the default restangular configuration
函数用来设置restangular 的默认配置
export function RestangularConfigFactory (RestangularProvider) {
RestangularProvider.setDefaultHeaders({'Authorization': 'Bearer UDXPx-Xko0w4BRKajozCVy20X11MRZs1'});
}
// AppModule is the main entry point into Angular2 bootstraping process
@NgModule({
...
imports: [
// Importing RestangularModule and making default configs for restanglar
//导入RestangularModule并为restanglar创建默认配置
RestangularModule.forRoot(RestangularConfigFactory),
]
})
export class AppModule {
}
The base URL for all calls to your API. For example if your URL for fetching accounts is http://example.com/api/v1/accounts, then your baseUrl is /api/v1. The default baseUrl is an empty string which resolves to the same url that Angular2 is running, but you can also set an absolute url like http://api.example.com/api/v1 if you need to set another domain.
所有API调用的基本URL。例如如果你有一个URL获取accounts ,这个URL是http://example.com/api/v1/accounts,那么你的baseUrl可以设置成为/api/V1。默认的baseUrl是空的字符串,它解析为Angular2正在运行的URL,但如果您需要设置另一个域,您也可以设置像http://api.example.com/api/v1这样的绝对URL。
This is a hook. After each element has been "restangularized" (Added the new methods from Restangular), the corresponding transformer will be called if it fits.
This should be used to add your own methods / functions to entities of certain types.
You can add as many element transformers as you want. The signature of this method can be one of the following:
addElementTransformer(route, transformer): Transformer is called with all elements that have been restangularized, no matter if they're collections or not.
addElementTransformer(route, isCollection, transformer): Transformer is called with all elements that have been restangularized and match the specification regarding if it's a collection or not (true | false)
向模型添加自定义方法
Create custom methods for your models using Restangular.extendModel(). This is an alias for:
使用Restangular.extendModel()为模型创建自定义方法。 这是一个别名:
RestangularProvider.addElementTransformer(route, false, fn);
Back to top
Example:
//为/accounts这个路由添加一个处理函数,比如你对/accounts/*这个路由发出了请求,
也就是你创建了一个restangular对象,然后使用这个对象获取数据,这个时候,
你可以为这个restangular的对象添加一个方法,这个方法就是prettifyAmount ,
然后返回这个对象,这样这个对象中就有了新的方法。我们就可以使用这个放来来进行处理
Restangular.extendModel('accounts', function(model) {
model.prettifyAmount = function() {};
return model;
});
var account$ = Restangular.one('accounts', 1).get();
account$.subscribe(function(account) {
account.prettifyAmount(); // invoke your custom model method
});
Use this property to control whether Restangularized elements to have a parent or not. So, for example if you get an account and then get a nested list of buildings, you may want the buildings URL to be simple /buildings/123 instead of /accounts/123/buildings/123. This property lets you do that. 使用此属性来控制Restangularized(Restangular化的)元素是否具有父级。
This method accepts 1 parameter, it could be: 方法有一个参数: Boolean: Specifies if all elements should be parentless or not 布尔:指定所有的资源都会被当作孤立资源处理,没有任何URL会进行嵌套 Array: Specifies the routes (types) of all elements that should be parentless. For example ['buildings'] 只有数组中的资源,才会被当作孤立的资源处理。
Let's assume that for most requests you need some configuration (The global one), and for just a bunch of methods you need another configuration. In that case, you'll need to create another Restangular service with this particular configuration. This scoped configuration will inherit all defaults from the global one. Let's see how.
我们假设对于大多数请求,您需要一些配置(全局配置),而对于一些方法,您需要另一个配置。 在这种情况下,您将需要使用此特定配置创建另一个Restangular服务。 此范围配置将从全局配置继承所有默认值。 我们来看看怎么样
// Function for settting the default restangular configuration
export function RestangularConfigFactory (RestangularProvider) {
RestangularProvider.setBaseUrl('http://www.google.com');
}
//Restangular service that uses Bing
export const RESTANGULAR_BING = new InjectionToken<any>('RestangularBing');
export function RestangularBingFactory(restangular: Restangular) {
return restangular.withConfig((RestangularConfigurer) => {
RestangularConfigurer.setBaseUrl('http://www.bing.com');
});
}
// AppModule is the main entry point into Angular2 bootstraping process
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
imports: [
// Global configuration
RestangularModule.forRoot(RestangularConfigFactory),
],
providers: [
{ provide: RESTANGULAR_BING, useFactory: RestangularBingFactory, deps: [Restangular] }
]
})
export class AppModule {}
// Let's use it in the component
@Component({
...
})
export class OtherComponent {
constructor(
@Inject(Restangular) public Restangular,
@Inject(RESTANGULAR_BING) public RestangularBing
) {}
ngOnInit() {
// GET to http://www.google.com/users
// Uses global configuration
Restangular.all('users').getList()
// GET to http://www.bing.com/users
// Uses Bing configuration which is based on Global one, therefore .json is added.
RestangularBing.all('users').getList()
}
};
Errors can be checked on the second argument of the subscribe. 错误能在subscribe中的第二个参数进行处理
Restangular.all("accounts").getList().subscribe( response => {
console.log("All ok");
}, errorResponse => {
console.log("Error with status code", errorResponse.status);//错误在这里进行处理
});
我想在每一个Restangular请求中添加认证token ,我该怎么做?
You can use setDefaultHeaders or addFullRequestInterceptor 你可以使用setDefaultHeaders 或者是 addFullRequestInterceptor
也就是说想要在头部加上认证token,只有两种方式: (1)setDefaultHeaders (2)addFullRequestInterceptor
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { RestangularModule } from 'ngx-restangular';
import { authService } from '../your-services';
// Function for settting the default restangular configuration
export function RestangularConfigFactory (RestangularProvider, authService) {
// set static header 设置静态的restAngular头部
RestangularProvider.setDefaultHeaders({'Authorization': 'Bearer UDXPx-Xko0w4BRKajozCVy20X11MRZs1'});
// by each request to the server receive a token and update headers with it
如果每次都是从服务器获取token,并且更新头部那么使用下面的方式
RestangularProvider.addFullRequestInterceptor((element, operation, path, url, headers, params) => {
let bearerToken = authService.getBearerToken();
return {
//注意这里
headers: Object.assign({}, headers, {Authorization: `Bearer ${bearerToken}`})
};
});
}
// AppModule is the main entry point into Angular2 bootstraping process
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
imports: [
// Importing RestangularModule and making default configs for restanglar
RestangularModule.forRoot([authService], RestangularConfigFactory),
]
})
export class AppModule {
}
怎样能让delete操作没有body?? You must add a requestInterceptor for this. 你可以在requestInterceptor 中添加这些:
RestangularProvider.setRequestInterceptor(function(elem, operation) {
if (operation === "remove") {//如果是remove操作,那么就返回null
return null;
}
return elem;//如果是其他的操作返回的是elem
})
我想在每一个Restangular 请求中添加一个header,我该怎么做? You can use defaultHeaders property for this. defaultsHeaders can be scoped with withConfig so it's really cool. 你可以使用defaultHeaders 属性来解决这个问题,
There are 3 sets of methods. Collections have some methods and elements have others. There are are also some common methods for all of them
有3套方法。 Collections 有一些方法和elements 有其他的。 集合和元素之间也有一些共同的方法。
Collections 方法 elements 方法 Collections 和elements 的共同方法
Restangular 方法
These are the methods that can be called on the Restangular object. Restangular 对象上可以调用的方法
one(route, id): This will create a new Restangular object that is just a pointer to one element with the route route and the specified id.
constructor(private route: ActivatedRoute, private restangular: Restangular, private router: Router) {
this.heroes = restangular.all("heroes");
}
ngOnInit() {
this.route.params.forEach((params: Params) => {
this.id = +params['id'];
});
//restangular的one方法的使用,
this.restangular.one("heroes", this.id).get().subscribe(res => {
this.hero = res;
});
}
all(route): This will create a new Restangular object that is just a pointer to a list of elements for the specified path.
export class HeroListComponent {
private heroes;
public heroList: Hero[];
constructor(public restangular: Restangular) {
this.heroes = restangular.all("heroes");//使用 restangular.all
}
ngOnInit() {
//使用 restangular.all().getList()
this.heroes.getList().subscribe(heroes => {
this.heroList = heroes;
});
}
}
//下面这些函数没有使用 oneUrl(route, url): This will create a new Restangular object that is just a pointer to one element with the specified URL.
allUrl(route, url): This creates a Restangular object that is just a pointer to a list at the specified URL.
copy(fromElement): This will create a copy of the from element so that we can modify the copied one.
restangularizeElement(parent, element, route, queryParams): Restangularizes a new element
restangularizeCollection(parent, element, route, queryParams): Restangularizes a new collection
There are 3 sets of methods. Collections have some methods and elements have others. There are are also some common methods for all of them
有3套方法。 Collections 有一些方法和elements 有其他的。 集合和元素之间也有一些共同的方法。
Collections 方法 elements 方法 Collections 和elements 的共同方法
元素方法
ngOnInit() {
this.route.params.forEach((params: Params) => {
this.id = +params['id'];
});
//这里在this.restangular.one上面调用的方法
this.restangular.one("heroes", this.id).get().subscribe(res => {
this.hero = res;
});
}
get([queryParams, headers]): Gets the element. Query params and headers are optionals
getList(subElement, [queryParams, headers]): Gets a nested resource. subElement is mandatory. It's a string with the name of the nested resource (and URL). For example buildings
put([queryParams, headers]): Does a put to the current element
post(subElement, elementToPost, [queryParams, headers]): Does a POST and creates a subElement. Subelement is mandatory and is the nested resource. Element to post is the object to post to the server
remove([queryParams, headers]): Does a DELETE. By default, remove sends a request with an empty object, which may cause problems with some servers or browsers. This shows how to configure RESTangular to have no payload.
head([queryParams, headers]): Does a HEAD
trace([queryParams, headers]): Does a TRACE
options([queryParams, headers]): Does a OPTIONS
patch(object, [queryParams, headers]): Does a PATCH
one(route, id): Used for RequestLess connections and URL Building. See section below.
all(route): Used for RequestLess connections and URL Building. See section below.
several(route, ids)*: Used for RequestLess connections and URL Building. See section below.
oneUrl(route, url): This will create a new Restangular object that is just a pointer to one element with the specified URL.
allUrl(route, url): This creates a Restangular object that is just a pointer to a list at the specified URL.
getRestangularUrl(): Gets the URL of the current object.
getRequestedUrl(): Gets the real URL the current object was requested with (incl. GET parameters). Will equal getRestangularUrl() when no parameters were used, before calling get(), or when using on a nested child.
getParentList(): Gets the parent list to which it belongs (if any)
clone(): Copies the element. It's an alias to calling Restangular.copy(elem).
plain(): Returns the plain element received from the server without any of the enhanced methods from Restangular. It's an alias to calling Restangular.stripRestangular(elem)
save: Calling save will determine whether to do PUT or POST accordingly
拷贝元素
Before modifying an object, we sometimes want to copy it and then modify the copied object. We can use Restangular.copy(fromElement).
在修改一个对象之前,我们有些时候想要拷贝它,并且修改拷贝的副本,我们可以使用
Restangular.copy(fromElement)
一个Observables值,直接在模板中使用
If you want to use values directly in templates use AsyncPipe 使用异步的管道的方式 “async”
this.accounts = this.restangular.all('accounts').getList();
<tr *ngFor="let account of accounts | async">
<td>{{account.fullName}}</td>
</tr>
Restangular comes with defaults for all of its properties but you can configure them. So, if you don't need to configure something, there's no need to add the configuration. You can set all these configurations in RestangularModule to change the global configuration, you can also use the withConfig method in Restangular service to create a new Restangular service with some scoped configuration or use withConfig in component to make specified Restangular
You can configure Restangular "withConfig" like in example below, you can also configure them globally RestangularModule or in service with withConfig 上面这句话的意思就是说配置restangular有两种方式,第一种方式是在app.moudule.ts文件中配置restangular.
【第一种方式:】
// Function for settting the default restangular configuration
函数用来设置默认的restangular配置
export function RestangularConfigFactory (RestangularProvider) {
RestangularProvider.setBaseUrl('http://www.google.com');
}
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
imports: [
// Global configuration
RestangularModule.forRoot(RestangularConfigFactory),
]
})
export class AppModule {}
【第二种方式:】
// Let's use it in the component
@Component({
...
})
export class OtherComponent {
constructor(private restangular: Restangular) {}
ngOnInit() {
//第二种方式,使用 restangular.withConfig方式配置restangular
restangular.withConfig((RestangularConfigurer) => {
RestangularConfigurer.setBaseUrl('http://www.bing.com');
}).all('users').getList()
}
};
一些中文的资料
http://www.cnblogs.com/iagw/p/6600777.html
Ngx-restangular
This project is the follow-up of the Restangular. Ngx-restangular is an Angular 2+ service that simplifies common GET, POST, DELETE, and UPDATE requests with a minimum of client code. It's a perfect fit for any WebApp that consumes data from a RESTful API.
这个项目是Restangular的后续工作。 Ngx-restangular是一种Angular 2+服务,可以使用最少的客户端代码简化常见的GET,POST,DELETE和UPDATE请求。 它适用于任何从RESTful API中消耗数据的WebApp。