Using HTTP Angular - http

I'm trying to make a simple HTTP request using Angular, but I keep getting this error:
Property 'http' does not exist on type 'WorksService'.
import {Injectable} from 'angular2/core';
import {Http, HTTP_PROVIDERS, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
export class Work {
constructor(public id: number, public name: string) { }
}
#Injectable()
export class WorksService {
constructor (private http: Http) {}
private _WorksUrl = 'api/projects'; // URL to web api
getHeroes () {
return this.http.get(this._WorksUrl)
.map(res => <Work[]> res.json().data)
.catch(this.handleError);
}
private handleError (error: Response) {
// instead of just logging it to the console
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}

I guess that you instantiate the service by your own. You need to get it through dependency injection so Angular2 will provide the http instance directly.
To do that, just add the service in providers either when bootstrapping your application or within the providers attribute of the component that uses the service (directly or indirectly).
bootstrap(AppComponent, [ HTTP_PROVIDERS, WorksService ]);
or
bootstrap(AppComponent, [ HTTP_PROVIDERS ]);
(...)
#Component({
(...)
providers: [ WorksService ]
})
export class SomeComponent {}
To inject it then, you do like this:
#Component({
(...)
})
export class SomeComponent {
constructor(private service WorksService) {
this.service.getHeroes().subscribe(
(data) => {
(...)
});
}
}

Related

from http to Http Client, cant get my object to become a string array [duplicate]

Following Google's official Angular 4.3.2 doc here, I was able to do a simple get request from a local json file. I wanted to practice hitting a real endpoint from JSON placeholder site, but I'm having trouble figuring out what to put in the .subscribe() operator. I made an IUser interface to capture the fields of the payload, but the line with .subscribe(data => {this.users = data}) throws the error Type 'Object' is not assignable to type 'IUser[]'. What's the proper way to handle this? Seems pretty basic but I'm a noob.
My code is below:
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { IUsers } from './users';
#Component({
selector: 'pm-http',
templateUrl: './http.component.html',
styleUrls: ['./http.component.css']
})
export class HttpComponent implements OnInit {
productUrl = 'https://jsonplaceholder.typicode.com/users';
users: IUsers[];
constructor(private _http: HttpClient) { }
ngOnInit(): void {
this._http.get(this.productUrl).subscribe(data => {this.users = data});
}
}
You actually have a few options here, but use generics to cast it to the type you're expecting.
// Notice the Generic of IUsers[] casting the Type for resulting "data"
this.http.get<IUsers[]>(this.productUrl).subscribe(data => ...
// or in the subscribe
.subscribe((data: IUsers[]) => ...
Also I'd recommend using async pipes in your template that auto subscribe / unsubscribe, especially if you don't need any fancy logic, and you're just mapping the value.
users: Observable<IUsers[]>; // different type now
this.users = this.http.get<IUsers[]>(this.productUrl);
// template:
*ngFor="let user of users | async"
I'm on the Angular doc team and one open todo item is to change these docs to show the "best practice" way to access Http ... which is through a service.
Here is an example:
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import { IProduct } from './product';
#Injectable()
export class ProductService {
private _productUrl = './api/products/products.json';
constructor(private _http: HttpClient) { }
getProducts(): Observable<IProduct[]> {
return this._http.get<IProduct[]>(this._productUrl)
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(err: HttpErrorResponse) {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
let errorMessage = '';
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
errorMessage = `An error occurred: ${err.error.message}`;
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
}
console.error(errorMessage);
return Observable.throw(errorMessage);
}
}
The component would then look like this:
ngOnInit(): void {
this._productService.getProducts()
.subscribe(products => this.products = products,
error => this.errorMessage = <any>error);
}

How to get both headers and JSON return with parameter in Angular 6

I am using Angular http request to get a JSON response from a wordpress rest API. When I pass a parameter I do not get a response, but without the parameter it is working fine.
Here is my code from wpgetpost.service.ts file
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders} from '#angular/common/http';
import { Observable } from 'rxjs';
import { GlobalService } from '../global/global.service';
#Injectable({
providedIn: 'root'
})
export class WpgetpostService {
constructor( private http: HttpClient, private URL: GlobalService ) { }
getPost(): Observable<any[]> {
const url = this.URL.WP_API_URL;
return this.http.get<any[]>(url, {
params: {
page: '2'
},
});
}
}
Also, how can I get the headers from this response?
as per WP documentation.
using the param within the same URL.
/wp/v2/posts?page=2

Angular2 redirect user to somewhere when JWT token expires and he currently is on guarded location

i'm using angular2-jwt package from auth0. Everything works fine, but now i am wondering how to redirect user, who is currently on some path, which is guarded with my auth guard, somewhere else. Now it is redirecting just when is user trying to get to the guarded path.
I know that i can hide objects in my component, but then i must do that in every single guarded component, which is not so clear.
Here are my routes:
const appRoutes: Routes = [
{path: 'login', component: LoginComponent},
{path: 'register', component: RegisterComponent},
{path: '', component: HomeComponent},
{path: 'user/edit', component: EditProfileComponent, canActivate: [AuthGuard]},
];
and this is my guard service:
...
#Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AuthService, private router: Router) {
}
canActivate() {
if (this.auth.loggedIn()) {
return true;
}
this.router.navigate(['/']);
return false;
}
}
Http interceptor
What you can do is implement a HTTP interceptor.
This HTTP interceptor can check for error codes like 401 (not authenticated) and/or 403 (fobidden, not authorized to access). With an implementation like this, you can also set the authorization headers of your requests each time you send a request to the server.
Make sure you are using HttpClient inside your application. The interceptor listens only for requests made by HttpClient.
Implementation
Step 1, create an error interceptor:
import { Router } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '#angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '#angular/common/http';
import { HttpErrorResponse } from '#angular/common/http';
import 'rxjs/add/operator/do';
#Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private router: Router) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).do(event => { }, err => {
if (err instanceof HttpErrorResponse && err.status == 401) {
this.router.navigateByUrl('/login');
} else if (err instanceof HttpErrorResponse && err.status == 403) {
this.router.navigate(['/not-authorized']);
}
});
}
}
Step 2, use the error interceptor:
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true
},
// ...
]
Useful links:
You can find more on interceptors inside the Angular documentation.
An implementation on the authentication interceptor is found here.

Angular 2 - How to handle HTTP responses in Component

New to Angular 2, still trying to get my head around certain things. Where I am stuck is I have login service and login component. I send a login request from the login component to the login service to post the username and password to a login API. If successful it posts the token to the localstorage. Where I am stuck is after the token is sent storage I want to return a boolean response back to the login component. Based on the boolean response it will perform execute a function in the component.
I can do everything until I get the response. I don't know how to handle a response back to the login component. Appreciate if someone could point me in the right direction. My code as follows:
LOGIN SERVICE
import { Injectable } from '#angular/core';
import { Token } from './login';
import { APIDOMAIN } from '../../../shared/api';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class LoginService {
url: string = APIDOMAIN;
constructor(private http: Http) { }
login(username: string, password: string) {
console.log('Login API');
let headers = new Headers();
let data = null;
headers.append("Authorization", "Basic " + btoa(username + ":" + password));
headers.append("Content-Type", "application/x-www-form-urlencoded");
this.http.post(this.url+ '/login', data, {headers: headers})
.map(res => res.json())
.subscribe(
token => { console.log(token); localStorage.setItem('id_token',token.token); },
err => { console.log(err);},
() => console.log('Request Complete')
);
}
logout(): void {
localStorage.removeItem('id_token');
}
}
LOGIN COMPONENT
import { Component, OnInit } from '#angular/core';
import { LoginService } from './shared/login.service';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
username: string;
password: string;
constructor(private loginService: LoginService) { }
ngOnInit() {}
login(): void {
this.loginService.login(this.username,this.password)
// PEFORM SOME FUNCTION BASED BOOLEAN RESPONSE
}
}
Here's one solution:
export class LoginService {
status: EventEmitter<boolean> = new EventEmitter();
login(username: string, password: string) {
this.http.post(...)
.map(res => res.json())
.subscribe(token => {
console.log(token);
localStorage.setItem('id_token',token.token);
this.status.emit(true);
});
logout() {
localStorage.removeItem('id_token');
this.status.emit(false);
}
}
export class LoginComponent implements OnInit {
constructor(private loginService: LoginService) { }
ngOnInit() {
this.loginService.status.subscribe(console.info);
}
}

Angular2 HTTP using observables subscribe showing data undefined

I don't know what I'm doing wrong but somehow i'm not able to read data, though the data is coming from server in response and even the data is getting showed inside service extractData method when I'm putting the console but in component inside subscribe function it is giving me undefined. Help me what I'm doing wrong, what I'm assuming is that this is the problem of async but, I have no idea how correct it.
Any help will be appreciable.
Thanx in advance
Component.ts
import { Component, Input, OnInit } from '#angular/core';
import {AdminService} from './admin.service';
import {logistics} from '../shared/model/logistics';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
import { Observable } from 'rxjs/Observable';
import {Response } from '#angular/http';
#Component({
moduleId:module.id,
selector: 'admin',
templateUrl: 'admin.component.html',
styleUrls:['admin.component.css'],
providers:[AdminService]
})
export class AdminComponent implements OnInit{
#Input() public allocatedAssetsList: logistics[];
mode = 'Observable';
public errorMsg = '';
constructor(private adminService: AdminService) {
}
ngOnInit(){
this.listByEmpId("123");
}
listByEmpId(empId:string){
this.adminService.getAllocatedAssets(empId).subscribe(
res => this.allocatedAssetsList = res,
error => this.errorMessage = <any>error);
}
}
Service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Hero } from './hero';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions } from '#angular/http';
import {logistics} from '../shared/model/logistics';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class AdminService {
constructor (private http: Http) {}
private listAssetsURL = '/api/logistics/list/'; // URL to web API
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError (error: any) {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
getAllocatedAssets (empId: string): Observable<logistics[]> {
this.listAssetsURL+= empId;
//let body = JSON.stringify({ empId });
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get(this.listAssetsURL)
.map(this.extractData)
.catch(this.handleError);
}
}
listByEmpId(empId:string){
this.adminService.getAllocatedAssets(empId).subscribe(
res => {
this.allocatedAssetsList = res;
console.log(this.allocatedAssetsList);
},
error => this.errorMessage = <any>error);
}
This is probably because you are trying to access your allocatedAssetsLists before the data is actually returned from the service.
If you are accessing it in your template you can use a simple ngIf to make sure you only try to display it once the data is available.
If this is not it, we need more information on your problem to help.

Resources