├── README.md ├── consumer-observable.ts ├── web-api-observable.service.js └── web-api-observable.service.ts /README.md: -------------------------------------------------------------------------------- 1 | # Restful Webservice For Angular2 Using Observable 2 | Restful implementation of GET, POST, DELETE, PATCH, PUT in Angular2 using Observable 3 | 4 | The Angular Http client communicates with the server using a familiar HTTP request/response protocol. The Http client is one of a family of services in the Angular HTTP library. When importing from the @angular/http module, SystemJS knows how to load services from the Angular HTTP library because the systemjs.config.js file maps to that module name. The HttpModule is necessary for making HTTP calls. 5 | 6 | Benefits of using Global Service (web-api-observable.service.ts): 7 | 8 | * This will contain shared/global service which will be consumed by all modules for executing CRUD operation, Request Type, URL, Parameter Object will be passed to this shared service, so it will make code more maintainable, readable and scalable 9 | 10 | * If we dont go through this method then we have to use $http.get() or $http.post method every where in services files of each module 11 | 12 | * content negotiation issues can be simply handled over here 13 | 14 | * If you want to append anything with each URL like ‘Http:\mydomain\’ then instead of copy it on every service file just hard-code this thing in this file and append URL from their respective services. 15 | 16 | * We don’t need to mention protocol and host-name now in every URL request. 17 | 18 | ---- 19 | 20 | ### Observable 21 | 22 | Think of an Observable as a stream of events published by some source. To listen for events in this stream, subscribe to the Observable. These subscriptions specify the actions to take when the web request produces a success event or a fail event (with the error in the payload). 23 | 24 | * The observable's map callback moves to the success parameter and its catch callback to the fail parameter in this pattern. 25 | 26 | * The errorHandler forwards an error message as a failed promise instead of a failed observable. 27 | 28 | ----- 29 | 30 | ### Observable vs Promises 31 | 32 | The less obvious but critical difference is that these two methods return very different results. 33 | 34 | * The **promise-based** then returns another promise. You can keep chaining more then and catch calls, getting a new promise each time. 35 | 36 | * The **subscribe method** returns a Subscription. A Subscription is not another Observable. It's the end of the line for observables. You can't call map on it or call subscribe again. The Subscription object has a different purpose, signified by its primary method, unsubscribe. 37 | 38 | ----- 39 | 40 | ### RxJS library 41 | 42 | * RxJS ("Reactive Extensions") is a 3rd party library, endorsed by Angular, that implements the asynchronous observable pattern. 43 | 44 | * RxJS npm package loaded via system.js because observables are used widely in Angular applications. 45 | 46 | * The app needs it when working with the HTTP client. Additionally, you must take a critical extra step to make RxJS observables usable. 47 | 48 | * The RxJS library is large. Size matters when building a production application and deploying it to mobile devices. You should include only necessary features. 49 | 50 | * Accordingly, Angular exposes a stripped down version of Observable in the rxjs/Observable module that lacks most of the operators such as the map method. 51 | 52 | * You could add every RxJS operator with a single import statement. While that is the easiest thing to do, you'd pay a penalty in extended launch time and application size because the full library is so big. 53 | 54 | * Since this app only uses a few operators, it's better to import each Observable operator and static class method, one-by-one, for a custom Observable implementation tuned precisely to the app's requirements. Put the import statements in one app/rxjs-operators.ts file. 55 | 56 | ----- 57 | 58 | ## HTTP GET Code (web-api-observable.service.ts) 59 | 60 | The Http.get method takes an object that implements RequestOptionsArgs as a second parameter. 61 | 62 | * #### Plain HTTP GET using Observable without any parameters 63 | 64 | getService(url: string): Observable { 65 | return this.http 66 | .get(url, this.options) 67 | .map(this.extractData) 68 | .catch(this.handleError); 69 | } 70 | 71 | **Consumer Code in _custom component_**: 72 | 73 | this.movieObservableService 74 | .getService('api/Movie/TestGetNo') 75 | .subscribe( 76 | result => console.log(result), 77 | error => this.errorMessage = error 78 | ); 79 | 80 | * #### HTTP GET using Observable with single query string term 81 | 82 | getServiceWithDynamicQueryTerm(url: string, key: string, val: string): Observable { 83 | return this.http 84 | .get(url + "/?" + key + "=" + val, this.options) 85 | .map(this.extractData) 86 | .catch(this.handleError); 87 | } 88 | 89 | **Consumer Code in _custom component_**: 90 | 91 | this.movieObservableService 92 | .getServiceWithDynamicQueryTerm('api/Movie/TestGetParam', "query", "hello") 93 | .subscribe( 94 | result => console.log(result), 95 | error => this.errorMessage = error 96 | ); 97 | 98 | * #### HTTP GET using Observable with multiple query string term 99 | 100 | getServiceWithMultipleQueryTerm(url: string, query: string): Observable { 101 | return this.http 102 | .get(url + "/?" + query, this.options) 103 | .map(this.extractData) 104 | .catch(this.handleError); 105 | } 106 | 107 | **Consumer Code in _custom component_**: 108 | 109 | this.movieObservableService 110 | .getServiceWithMultipleQueryTerm('api/Movie/TestGetParam', "id=1&&name=abc") 111 | .subscribe( 112 | result => console.log(result), 113 | error => this.errorMessage = error 114 | ); 115 | 116 | * #### HTTP GET using Observable with hardcode query string term 117 | 118 | *The search field of that object can be used to set a string or a URLSearchParams object.* 119 | 120 | getServiceWithFixedQueryString(url: string, param: any): Observable { 121 | this.options = new RequestOptions({ headers: this.headers, search: 'query=' + param }); 122 | return this.http 123 | .get(url, this.options) 124 | .map(this.extractData) 125 | .catch(this.handleError); 126 | } 127 | 128 | **Consumer Code in _custom component_**: 129 | 130 | this.movieObservableService 131 | .getServiceWithFixedQueryString('api/Movie/TestGetParam', 'abc') 132 | .subscribe( 133 | result => console.log(result), 134 | error => this.errorMessage = error 135 | ); 136 | 137 | * #### HTTP GET using Observable with complex object as query string 138 | 139 | *The search field of that object can be used to set a string or a URLSearchParams object.* 140 | 141 | getServiceWithComplexObjectAsQueryString(url: string, param: any): Observable { 142 | let params: URLSearchParams = new URLSearchParams(); 143 | for (var key in param) { 144 | if (param.hasOwnProperty(key)) { 145 | let val = param[key]; 146 | params.set(key, val); 147 | } 148 | } 149 | this.options = new RequestOptions({ headers: this.headers, search: params }); 150 | return this.http 151 | .get(url, this.options) 152 | .map(this.extractData) 153 | .catch(this.handleError); 154 | } 155 | 156 | **Consumer Code in _custom component_**: 157 | 158 | this.movieObservableService 159 | .getServiceWithComplexObjectAsQueryString('api/Movie/TestGet', "{ id: '1', name: 'abc'}") 160 | .subscribe( 161 | result => console.log("4. getServiceWithComplexObjectAsQueryString: " + result), 162 | error => this.errorMessage = error 163 | ); 164 | 165 | ## HTTP POST Producer Code (web-api-observable.service.ts) 166 | 167 | The Http.post method takes body as second parameter and an object that implements RequestOptionsArgs as a third parameter. 168 | 169 | * #### HTTP POST using Observable with body object as parameter 170 | 171 | createService(url: string, param: any): Observable { 172 | let body = JSON.stringify(param); 173 | return this.http 174 | .post(url, body, this.options) 175 | .map(this.extractData) 176 | .catch(this.handleError); 177 | } 178 | 179 | **Consumer Code in _custom component_**: 180 | 181 | this.movieObservableService 182 | .createService('api/Movie/TestPost', "{ id: '1', name: 'abc'}") 183 | .subscribe( 184 | result => console.log(result), 185 | error => this.errorMessage = error 186 | ); 187 | 188 | ## HTTP PUT Producer Code (web-api-observable.service.ts) 189 | 190 | The Http.put method takes body as second parameter and an object that implements RequestOptionsArgs as a third parameter. 191 | 192 | * #### HTTP PUT using Observable with body object as parameter 193 | 194 | updateService(url: string, param: any): Observable { 195 | let body = JSON.stringify(param); 196 | return this.http 197 | .put(url, body, this.options) 198 | .map(this.extractData) 199 | .catch(this.handleError); 200 | } 201 | 202 | **Consumer Code in _custom component_**: 203 | 204 | this.movieObservableService 205 | .updateService('api/Movie/TestPost', "{ id: '1', name: 'abc'}") 206 | .subscribe( 207 | result => console.log(result), 208 | error => this.errorMessage = error 209 | ); 210 | 211 | ## HTTP PATCH Producer Code (web-api-observable.service.ts) 212 | 213 | The Http.patch method takes body as second parameter and an object that implements RequestOptionsArgs as a third parameter. 214 | 215 | * #### HTTP PATCH using Observable with body object as parameter 216 | 217 | patchService(url: string, param: any): Observable { 218 | let body = JSON.stringify(param); 219 | return this.http 220 | .patch(url, body, this.options) 221 | .map(this.extractData) 222 | .catch(this.handleError); 223 | } 224 | 225 | **Consumer Code in _custom component_**: 226 | 227 | this.movieObservableService 228 | .patchService('api/Movie/TestPost', "{ id: '1', name: 'abc'}") 229 | .subscribe( 230 | result => console.log(result), 231 | error => this.errorMessage = error 232 | ); 233 | 234 | ## HTTP DELETE Producer Code (web-api-observable.service.ts) 235 | 236 | The Http.delete method takes an object that implements RequestOptionsArgs as a second parameter. 237 | 238 | * #### HTTP DELETE using Observable with ID as parameter 239 | 240 | deleteServiceWithId(url: string, key: string, val: string): Observable { 241 | return this.http 242 | .delete(url + "/?" + key + "=" + val, this.options) 243 | .map(this.extractData) 244 | .catch(this.handleError); 245 | } 246 | 247 | **Consumer Code in _custom component_**: 248 | 249 | this.movieObservableService 250 | .deleteServiceWithId('api/Movie/TestDeleteWithId', "id", "8631") 251 | .subscribe( 252 | result => console.log(result), 253 | error => this.errorMessage = error 254 | ); 255 | 256 | * #### HTTP DELETE using Observable with complex object as parameter 257 | 258 | *The search field of that object can be used to set a string or a URLSearchParams object.* 259 | 260 | deleteService(url: string, param: any): Observable { 261 | let params: URLSearchParams = new URLSearchParams(); 262 | for (var key in param) { 263 | if (param.hasOwnProperty(key)) { 264 | let val = param[key]; 265 | params.set(key, val); 266 | } 267 | } 268 | this.options = new RequestOptions({ headers: this.headers, search: params }); 269 | return this.http 270 | .delete(url, this.options) 271 | .map(this.extractData) 272 | .catch(this.handleError); 273 | } 274 | 275 | **Consumer Code in _custom component_**: 276 | 277 | this.movieObservableService 278 | .deleteService('api/Movie/TestPost', "{ id: '1', name: 'abc'}") 279 | .subscribe( 280 | result => console.log(result), 281 | error => this.errorMessage = error 282 | ); 283 | 284 | #### Important Note 285 | 286 | **You need to append Accept headers to your get request in order for Firefox to render the json that comes back.** 287 | 288 | In the headers object, the Content-Type specifies that the body represents JSON. The headers object is used to configure the options object. The options object is a new instance of RequestOptions, a class that allows you to specify certain settings when instantiating a request. In this way, headers is one of the RequestOptions. 289 | 290 | In the return statement, options is the third argument of the post method, as shown above. 291 | 292 | ngOnInit() { 293 | let headers = new Headers(); 294 | headers.append('Accept', 'q=0.8;application/json;q=0.9'); 295 | return this.http.get(this.url, { headers: headers } ) 296 | .map(data => console.log(data.json())) 297 | .subscribe(err => console.log(err)); 298 | } 299 | 300 | ----- 301 | 302 | # Restful HTTP Service using Observable 303 | 304 | Angular injects a WebApiObservableService into the constructor and the component calls that service to fetch and save data. The component does not talk directly to the Angular Http client. The component doesn't know or care how it gets the data. It delegates to the WebApiObservableService. **This is a golden rule: always delegate data access to a supporting service class.** 305 | 306 | import { Injectable } from '@angular/core'; 307 | import { Http, Response, Headers, RequestOptions, URLSearchParams } from '@angular/http'; 308 | import { Observable } from 'rxjs/Observable'; 309 | 310 | // Observable class extensions 311 | import 'rxjs/add/observable/of'; 312 | import 'rxjs/add/observable/throw'; 313 | 314 | // Observable operators 315 | import 'rxjs/add/operator/catch'; 316 | import 'rxjs/add/operator/debounceTime'; 317 | import 'rxjs/add/operator/distinctUntilChanged'; 318 | import 'rxjs/add/operator/do'; 319 | import 'rxjs/add/operator/filter'; 320 | import 'rxjs/add/operator/map'; 321 | import 'rxjs/add/operator/switchMap'; 322 | 323 | import { ToasterService } from './alert.service'; 324 | import { LoaderService } from './loader.service'; 325 | 326 | @Injectable() 327 | export class WebApiObservableService { 328 | headers: Headers; 329 | options: RequestOptions; 330 | 331 | constructor(private http: Http, 332 | private toasterService: ToasterService, 333 | private loaderService: LoaderService) { 334 | this.headers = new Headers({ 'Content-Type': 'application/json', 335 | 'Accept': 'q=0.8;application/json;q=0.9' }); 336 | this.options = new RequestOptions({ headers: this.headers }); 337 | } 338 | 339 | getService(url: string): Observable { 340 | return this.http 341 | .get(url, this.options) 342 | .map(this.extractData) 343 | .catch(this.handleError); 344 | } 345 | 346 | getServiceWithDynamicQueryTerm(url: string, key: string, val: string): Observable { 347 | return this.http 348 | .get(url + "/?" + key + "=" + val, this.options) 349 | .map(this.extractData) 350 | .catch(this.handleError); 351 | } 352 | 353 | getServiceWithMultipleQueryTerm(url: string, query: string): Observable { 354 | return this.http 355 | .get(url + "/?" + query, this.options) 356 | .map(this.extractData) 357 | .catch(this.handleError); 358 | } 359 | 360 | getServiceWithFixedQueryString(url: string, param: any): Observable { 361 | this.options = new RequestOptions({ headers: this.headers, search: 'query=' + param }); 362 | return this.http 363 | .get(url, this.options) 364 | .map(this.extractData) 365 | .catch(this.handleError); 366 | } 367 | 368 | getServiceWithComplexObjectAsQueryString(url: string, param: any): Observable { 369 | let params: URLSearchParams = new URLSearchParams(); 370 | for (var key in param) { 371 | if (param.hasOwnProperty(key)) { 372 | let val = param[key]; 373 | params.set(key, val); 374 | } 375 | } 376 | this.options = new RequestOptions({ headers: this.headers, search: params }); 377 | return this.http 378 | .get(url, this.options) 379 | .map(this.extractData) 380 | .catch(this.handleError); 381 | } 382 | 383 | createService(url: string, param: any): Observable { 384 | let body = JSON.stringify(param); 385 | return this.http 386 | .post(url, body, this.options) 387 | .map(this.extractData) 388 | .catch(this.handleError); 389 | } 390 | 391 | updateService(url: string, param: any): Observable { 392 | let body = JSON.stringify(param); 393 | return this.http 394 | .put(url, body, this.options) 395 | .map(this.extractData) 396 | .catch(this.handleError); 397 | } 398 | 399 | patchService(url: string, param: any): Observable { 400 | let body = JSON.stringify(param); 401 | return this.http 402 | .patch(url, body, this.options) 403 | .map(this.extractData) 404 | .catch(this.handleError); 405 | } 406 | 407 | deleteService(url: string, param: any): Observable { 408 | let params: URLSearchParams = new URLSearchParams(); 409 | for (var key in param) { 410 | if (param.hasOwnProperty(key)) { 411 | let val = param[key]; 412 | params.set(key, val); 413 | } 414 | } 415 | this.options = new RequestOptions({ headers: this.headers, search: params }); 416 | return this.http 417 | .delete(url, this.options) 418 | .map(this.extractData) 419 | .catch(this.handleError); 420 | } 421 | 422 | deleteServiceWithId(url: string, key: string, val: string): Observable { 423 | return this.http 424 | .delete(url + "/?" + key + "=" + val, this.options) 425 | .map(this.extractData) 426 | .catch(this.handleError); 427 | } 428 | 429 | private extractData(res: Response) { 430 | let body = res.json(); 431 | return body || {}; 432 | } 433 | 434 | private handleError(error: any) { 435 | let errMsg = (error.message) ? error.message : 436 | error.status ? `${error.status} - ${error.statusText}` : 'Server error'; 437 | console.error(errMsg); 438 | this.toasterService.showToaster('error', 'Oops!! An error occurred', errMsg); 439 | this.loaderService.displayLoader(false); 440 | return Observable.throw(errMsg); 441 | } 442 | } 443 | 444 | [Text Reference](https://angular.io/docs/ts/latest/guide/server-communication.html) 445 | -------------------------------------------------------------------------------- /consumer-observable.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { SearchMovieModel } from './search-movie.model'; 4 | import { WebApiObservableService } from './web-api-observable.service'; 5 | 6 | @Component({ 7 | selector: 'search-movie-list', 8 | templateUrl: '../../Scripts/app/search-movies/search-movie-list/search-movie-list.component.html' 9 | }) 10 | 11 | export class SearchMovieListComponent implements OnInit { 12 | 13 | constructor( 14 | private movieObservableService: WebApiObservableService) { 15 | this.searchMovieModel = {id: '12' , name: 'abc'}; 16 | } 17 | 18 | ngOnInit() { 19 | this.movieObservableService 20 | .getService('api/Movie/TestGetNo') 21 | .subscribe( 22 | result => console.log("1. getService: " + result), 23 | error => this.errorMessage = error 24 | ); 25 | 26 | this.movieObservableService 27 | .getServiceWithDynamicQueryTerm('api/Movie/TestGetParam', "query", "hello") 28 | .subscribe( 29 | result => console.log("2. getServiceWithDynamicQueryTerm: " + result), 30 | error => this.errorMessage = error 31 | ); 32 | 33 | this.movieObservableService 34 | .getServiceWithFixedQueryString('api/Movie/TestGetParam', this.searchMovieModel.name) 35 | .subscribe( 36 | result => console.log("3. getServiceWithFixedQueryString: " + result), 37 | error => this.errorMessage = error 38 | ); 39 | 40 | this.movieObservableService 41 | .getServiceWithComplexObjectAsQueryString('api/Movie/TestGet', this.searchMovieModel) 42 | .subscribe( 43 | result => console.log("4. getServiceWithComplexObjectAsQueryString: " + result), 44 | error => this.errorMessage = error 45 | ); 46 | 47 | this.movieObservableService 48 | .createService('api/Movie/TestPost', this.searchMovieModel) 49 | .subscribe( 50 | result => console.log("5. createService: " + result), 51 | error => this.errorMessage = error 52 | ); 53 | 54 | this.movieObservableService 55 | .updateService('api/Movie/TestPut', this.searchMovieModel) 56 | .subscribe( 57 | result => console.log("6. updateService: " + result), 58 | error => this.errorMessage = error 59 | ); 60 | 61 | this.movieObservableService 62 | .patchService('api/Movie/TestPatch', this.searchMovieModel) 63 | .subscribe( 64 | result => console.log("7. patchService: " + result), 65 | error => this.errorMessage = error 66 | ); 67 | 68 | this.movieObservableService 69 | .deleteService('api/Movie/TestDelete', this.searchMovieModel) 70 | .subscribe( 71 | result => console.log("8. deleteService: " + result), 72 | error => this.errorMessage = error 73 | ); 74 | 75 | this.movieObservableService 76 | .deleteServiceWithId('api/Movie/TestDeleteWithId', "id", "8631") 77 | .subscribe( 78 | result => console.log("9. deleteServiceWithId: " + result), 79 | error => this.errorMessage = error 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /web-api-observable.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var http_1 = require('@angular/http'); 13 | var Observable_1 = require('rxjs/Observable'); 14 | // Observable class extensions 15 | require('rxjs/add/observable/of'); 16 | require('rxjs/add/observable/throw'); 17 | // Observable operators 18 | require('rxjs/add/operator/catch'); 19 | require('rxjs/add/operator/debounceTime'); 20 | require('rxjs/add/operator/distinctUntilChanged'); 21 | require('rxjs/add/operator/do'); 22 | require('rxjs/add/operator/filter'); 23 | require('rxjs/add/operator/map'); 24 | require('rxjs/add/operator/switchMap'); 25 | 26 | var WebApiObservableService = (function () { 27 | function WebApiObservableService(http, toasterService, loaderService) { 28 | this.http = http; 29 | this.toasterService = toasterService; 30 | this.loaderService = loaderService; 31 | this.headers = new http_1.Headers({ 'Content-Type': 'application/json', 'Accept': 'q=0.8;application/json;q=0.9' }); 32 | this.options = new http_1.RequestOptions({ headers: this.headers }); 33 | } 34 | WebApiObservableService.prototype.getService = function (url) { 35 | return this.http 36 | .get(url, this.options) 37 | .map(this.extractData) 38 | .catch(this.handleError); 39 | }; 40 | WebApiObservableService.prototype.getServiceWithDynamicQueryTerm = function (url, key, val) { 41 | return this.http 42 | .get(url + "/?" + key + "=" + val, this.options) 43 | .map(this.extractData) 44 | .catch(this.handleError); 45 | }; 46 | WebApiObservableService.prototype.getServiceWithFixedQueryString = function (url, param) { 47 | this.options = new http_1.RequestOptions({ headers: this.headers, search: 'query=' + param }); 48 | return this.http 49 | .get(url, this.options) 50 | .map(this.extractData) 51 | .catch(this.handleError); 52 | }; 53 | WebApiObservableService.prototype.getServiceWithComplexObjectAsQueryString = function (url, param) { 54 | var params = new http_1.URLSearchParams(); 55 | for (var key in param) { 56 | if (param.hasOwnProperty(key)) { 57 | var val = param[key]; 58 | params.set(key, val); 59 | } 60 | } 61 | this.options = new http_1.RequestOptions({ headers: this.headers, search: params }); 62 | return this.http 63 | .get(url, this.options) 64 | .map(this.extractData) 65 | .catch(this.handleError); 66 | }; 67 | WebApiObservableService.prototype.createService = function (url, param) { 68 | var body = JSON.stringify(param); 69 | return this.http 70 | .post(url, body, this.options) 71 | .map(this.extractData) 72 | .catch(this.handleError); 73 | }; 74 | WebApiObservableService.prototype.updateService = function (url, param) { 75 | var body = JSON.stringify(param); 76 | return this.http 77 | .put(url, body, this.options) 78 | .map(this.extractData) 79 | .catch(this.handleError); 80 | }; 81 | WebApiObservableService.prototype.patchService = function (url, param) { 82 | var body = JSON.stringify(param); 83 | return this.http 84 | .patch(url, body, this.options) 85 | .map(this.extractData) 86 | .catch(this.handleError); 87 | }; 88 | WebApiObservableService.prototype.deleteService = function (url, param) { 89 | var params = new http_1.URLSearchParams(); 90 | for (var key in param) { 91 | if (param.hasOwnProperty(key)) { 92 | var val = param[key]; 93 | params.set(key, val); 94 | } 95 | } 96 | this.options = new http_1.RequestOptions({ headers: this.headers, search: params }); 97 | return this.http 98 | .delete(url, this.options) 99 | .map(this.extractData) 100 | .catch(this.handleError); 101 | }; 102 | WebApiObservableService.prototype.deleteServiceWithId = function (url, key, val) { 103 | return this.http 104 | .delete(url + "/?" + key + "=" + val, this.options) 105 | .map(this.extractData) 106 | .catch(this.handleError); 107 | }; 108 | WebApiObservableService.prototype.extractData = function (res) { 109 | var body = res.json(); 110 | return body || {}; 111 | }; 112 | WebApiObservableService.prototype.handleError = function (error) { 113 | var errMsg = (error.message) ? error.message : 114 | error.status ? error.status + " - " + error.statusText : 'Server error'; 115 | console.error(errMsg); 116 | return Observable_1.Observable.throw(errMsg); 117 | }; 118 | WebApiObservableService = __decorate([ 119 | core_1.Injectable(), 120 | __metadata('design:paramtypes', [http_1.Http]) 121 | ], WebApiObservableService); 122 | return WebApiObservableService; 123 | }()); 124 | exports.WebApiObservableService = WebApiObservableService; 125 | //# sourceMappingURL=web-api-observable.service.js.map 126 | -------------------------------------------------------------------------------- /web-api-observable.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers, RequestOptions, URLSearchParams } from '@angular/http'; 3 | import { Observable } from 'rxjs/Observable'; 4 | 5 | // Observable class extensions 6 | import 'rxjs/add/observable/of'; 7 | import 'rxjs/add/observable/throw'; 8 | 9 | // Observable operators 10 | import 'rxjs/add/operator/catch'; 11 | import 'rxjs/add/operator/debounceTime'; 12 | import 'rxjs/add/operator/distinctUntilChanged'; 13 | import 'rxjs/add/operator/do'; 14 | import 'rxjs/add/operator/filter'; 15 | import 'rxjs/add/operator/map'; 16 | import 'rxjs/add/operator/switchMap'; 17 | 18 | @Injectable() 19 | export class WebApiObservableService { 20 | headers: Headers; 21 | options: RequestOptions; 22 | 23 | constructor(private http: Http, 24 | private toasterService: ToasterService, 25 | private loaderService: LoaderService) { 26 | this.headers = new Headers({ 'Content-Type': 'application/json', 'Accept': 'q=0.8;application/json;q=0.9' }); 27 | this.options = new RequestOptions({ headers: this.headers }); 28 | } 29 | 30 | getService(url: string): Observable { 31 | return this.http 32 | .get(url, this.options) 33 | .map(this.extractData) 34 | .catch(this.handleError); 35 | } 36 | 37 | getServiceWithDynamicQueryTerm(url: string, key: string, val: string): Observable { 38 | return this.http 39 | .get(url + "/?" + key + "=" + val, this.options) 40 | .map(this.extractData) 41 | .catch(this.handleError); 42 | } 43 | 44 | getServiceWithFixedQueryString(url: string, param: any): Observable { 45 | this.options = new RequestOptions({ headers: this.headers, search: 'query=' + param }); 46 | return this.http 47 | .get(url, this.options) 48 | .map(this.extractData) 49 | .catch(this.handleError); 50 | } 51 | 52 | getServiceWithComplexObjectAsQueryString(url: string, param: any): Observable { 53 | let params: URLSearchParams = new URLSearchParams(); 54 | for (var key in param) { 55 | if (param.hasOwnProperty(key)) { 56 | let val = param[key]; 57 | params.set(key, val); 58 | } 59 | } 60 | this.options = new RequestOptions({ headers: this.headers, search: params }); 61 | return this.http 62 | .get(url, this.options) 63 | .map(this.extractData) 64 | .catch(this.handleError); 65 | } 66 | 67 | createService(url: string, param: any): Observable { 68 | let body = JSON.stringify(param); 69 | return this.http 70 | .post(url, body, this.options) 71 | .map(this.extractData) 72 | .catch(this.handleError); 73 | } 74 | 75 | updateService(url: string, param: any): Observable { 76 | let body = JSON.stringify(param); 77 | return this.http 78 | .put(url, body, this.options) 79 | .map(this.extractData) 80 | .catch(this.handleError); 81 | } 82 | 83 | patchService(url: string, param: any): Observable { 84 | let body = JSON.stringify(param); 85 | return this.http 86 | .patch(url, body, this.options) 87 | .map(this.extractData) 88 | .catch(this.handleError); 89 | } 90 | 91 | deleteService(url: string, param: any): Observable { 92 | let params: URLSearchParams = new URLSearchParams(); 93 | for (var key in param) { 94 | if (param.hasOwnProperty(key)) { 95 | let val = param[key]; 96 | params.set(key, val); 97 | } 98 | } 99 | this.options = new RequestOptions({ headers: this.headers, search: params }); 100 | return this.http 101 | .delete(url, this.options) 102 | .map(this.extractData) 103 | .catch(this.handleError); 104 | } 105 | 106 | deleteServiceWithId(url: string, key: string, val: string): Observable { 107 | return this.http 108 | .delete(url + "/?" + key + "=" + val, this.options) 109 | .map(this.extractData) 110 | .catch(this.handleError); 111 | } 112 | 113 | private extractData(res: Response) { 114 | let body = res.json(); 115 | return body || {}; 116 | } 117 | 118 | private handleError(error: any) { 119 | let errMsg = (error.message) ? error.message : 120 | error.status ? `${error.status} - ${error.statusText}` : 'Server error'; 121 | console.error(errMsg); 122 | return Observable.throw(errMsg); 123 | } 124 | } 125 | --------------------------------------------------------------------------------