I am actually searching for the user's location (at least geographical region) api which can be used easily with Angular2 typescript code.
import { Injectable} from '#angular/core';
import { Observable } from 'rxjs/Observable';
import {Http} from '#angular/http';
import 'rxjs/Rx';
#Injectable()
export class CurrentLocationService {
constructor(private _http: Http) {}
getCurrentLocation(): Observable<any> {
return this._http.get('http://ipinfo.io/json?callback=JSON_CALLBACK')
.map(response => response.json())
.catch(error => {
console.log(error);
return Observable.throw(error.json());
});
}
}
Related
I am having the following error in an Angular 7 app:
Property 'post' does not exist on type 'HttpClient'
The code that I am using is in the following:
import { Injectable } from '#angular/core';
import { Car } from '../models/car';
import cars from '../cars/car-list';
import { HttpClient } from 'selenium-webdriver/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class CarService {
private cars: Car[];
constructor(private http:HttpClient) {
this.cars = cars;
}
addCar(car: Car): Observable<any> {
this.cars.push(car);
return this.http.post('http://localhost:3000/cars', car);
}
Can you help me sort out this error?!
Thanks in advance for your help.
Change:
import { HttpClient } from 'selenium-webdriver/http';
to:
import { HttpClient } from '#angular/common/http';
And also import HttpClientModule in components parent module
I am new to Angular and I am trying to implement api call which send token in header on all api so I am using Interceptor.
I am not able to set header in request.
jwt.interceptor.ts
import { Injectable } from '#angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor() { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let currentUser = localStorage.getItem('useremail')
let currentUserToken = localStorage.getItem('token')
if (currentUser && currentUserToken) {
request = request.clone({
setHeaders: {
'Authorization': `${currentUserToken}`
}
});
}
// console.log("Request", request)
return next.handle(request);
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { AppUserListingComponent } from './app-user-listing/app-user-listing.component';
import { JwtInterceptor } from './jwt.interceptor';
#NgModule({
providers: [ { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true } ],
bootstrap: [AppComponent]
})
export class AppModule { }
user-listing.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class UserListingService {
apiUrl = "URL";
constructor(
private http: HttpClient
) { }
fetchAllUsers() {
return this.http.get(`${this.apiUrl}/fetchAdminsUsers`)
}
}
What is the reason my code is not working ?
Thanks in advance
In your app.module.ts code there's no import: [HttpClientModule] Do you have imported the HttpClientModule?
I'm experiencing a similar issue with angular 8.x http interceptor is not working OK.
Add imports: [BrowserModule, HttpClientModule] in #NgModule.
Authorization is a special header, you need to add withCredentials: true to the request to add it.
request = request.clone({
setHeaders: {
'Authorization': `${currentUserToken}`
},
withCredentials: true
});
try using instance of like below.
return next.handle(request).pipe(
tap(
event => {
if(event instanceof HttpResponse){
//api call success
console.log('success in calling API : ', event);
}
},
error => {
if(event instanceof HttpResponse){
//api call error
console.log('error in calling API : ', event);
}
}
)
)
I am trying to create a toast using Material Snackbar from a custom class.
I am getting an error in my custom class ( Unable to find open from undefined. ) but working fine in user.service.ts
If ngZone is used, then i am getting an error, (unable to find run from undefined)
Note: In ErrorHandler Class
console.log(this.snackBar) // gives undefined
app.module.ts
providers: [ErrorHandler],
bootstrap: [AppComponent]
})
export class AppModule { }
User Service
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { catchError } from 'rxjs/operators';
import { environment } from '../../environments/environment';
import { ErrorHandler } from '../classes/error-handler';
import {MatSnackBar} from '#angular/material';
#Injectable({
providedIn: 'root'
})
export class UserService {
private url = environment.api+'/login';
constructor(private http: HttpClient, private eh:ErrorHandler, private sb: MatSnackBar) { }
login(credentials){
this.sb.open("hello world"); // Working Fine
return this.http.post(this.url, {})
.pipe(
catchError(this.eh.handleError)
);
}
}
Error Handler Class
import {Component, Injectable, NgZone} from '#angular/core';
import { HttpErrorResponse } from '#angular/common/http';
import { throwError } from 'rxjs';
import * as _ from 'lodash';
import {MatSnackBar} from '#angular/material';
#Injectable({
providedIn: 'root'
})
export class ErrorHandler {
constructor (private snackBar: MatSnackBar) {}
public handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error("Error code working")
console.log(this.snackBar) // gives undefined
this.snackBar.open("Hello world"); // Throwing Error
}
// return an observable with a user-facing error message
return throwError('Something bad happened; please try again later.');
};
}
Thanks to all. I fixed it. Unfortunately i missed the stackoverflow link.
Change in
catchError((res) => this.eh.handleError(res))
did the trick
UserService
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { catchError } from 'rxjs/operators';
import { environment } from '../../environments/environment';
import { ErrorHandler } from '../classes/error-handler';
import {MatSnackBar} from '#angular/material';
#Injectable({
providedIn: 'root'
})
export class UserService {
private url = environment.api+'/login';
constructor(private http: HttpClient, private eh:ErrorHandler, private sb: MatSnackBar) { }
login(credentials){
this.sb.open("hello world"); // Working Fine
return this.http.post(this.url, {})
.pipe(
catchError((res) => this.eh.handleError(res)) // change in this line
);
}
}
I stumbled upon the same issue in my application a few days ago. The reason is the context of this.
In
This.sb.open("hello world"); // Working Fine
the context of this is the UserService class. While in
this.snackBar.open("Hello world"); // Throwing Error
the context of this changed. Probably to CatchSubscriber.
You already mentioned that:
catchError((res) => this.eh.handleError(res)) // change in this line
resolves the error. Because it changed the context of this back to the UserService class. An alternative solution is to use the arrow syntax for the whole login():
login = (credentials) => {
// your code goes here
}
Taking again the tutorial of the site Angular, I created in winamp a database with a table including a field {"id": id, "name": name} and I make 2 queries on this table with Symfony4:
1) A request to list heroes.
2) A request to create hero.
Executed from Angular 7, the query 1) works perfectly (route / listerHeroes).
Executed from Angular 7, query 2) does not work, it returns error 405 (route / ajouterHero). However launched from Postman, this query works.
I can not find any documentation to explain to me this bug on which I stumble for several days. A track please
Below copy of both classes: heroes.service.ts and component3.component.ts
// heroes.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { HttpErrorHandler, HandleError } from './http-error-handler.service';
import { Hero } from '../assets/Structure';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
#Injectable({ providedIn: 'root' })
export class HeroesService {
heroesUrl = 'http://heroes/';
private handleError: HandleError;
constructor(private http: HttpClient, httpErrorHandler: HttpErrorHandler) {
this.handleError = httpErrorHandler.createHandleError('HeroesService');
}
getHeroes$(): Observable<Hero[]> {
return this.http.get<Hero[]>(`${this.heroesUrl}listerHeroes`, httpOptions);
}
addHero(hero: Hero): Observable<Hero> {
return this.http
.post<Hero>(`${this.heroesUrl}ajouterHero`, hero, httpOptions)
.pipe(catchError(this.handleError('addHero', hero)));
}
}
// component3.component.ts
import { Component, OnInit } from '#angular/core';
import { HeroesService } from '../heroes.service';
import { Hero } from '../../assets/Structure';
#Component({
selector: 'app-component3',
templateUrl: './component3.component.html',
styleUrls: ['./component3.component.css']
})
export class Component3Component implements OnInit {
heroes: Hero[];
editHero: Hero;
constructor(private heroesService: HeroesService) {}
ngOnInit() {
this.heroesService.getHeroes$().subscribe(res => (this.heroes = res));
}
addHero(name: string): void {
name = name.trim();
console.log('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF C3A name =', name);
if (!name) {
return;
}
const newHero: Hero = { 'id': 0, 'name': name } as Hero;
this.heroesService.addHero(newHero).subscribe(hero => {
console.log('GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG C3B hero= ', hero);
this.heroes.push(hero);
});
}
}
I found the solution:
The blocking was listed backend (Symfony4) which refused the pre-query OPTIONS. It was necessary to install and configure the bundle nelmio (https://github.com/nelmio/NelmioApiDocBundle) which allows the smooth running of the request.
I have created a project including angular2 for front-end and i also created webapi project to consume data from database.
Controller Code return model:
UserInfo = JsonConvert.DeserializeObject<List<UsersVM>>(Response);
I want to iterate over this data model in my angular view. i trid creating angular http calls. but this not acceptable in my case. i need to call webapi from my mvc controllers and just to render that data from angular2 views.
Angular Model is :
export interface IUser {
Id: number;
ProductName: string;
ProductPrice: string;
}
Angular Service Code is:
import {
Injectable
} from '#angular/core';
import {
Http, Response, RequestOptions,
Request, RequestMethod, Headers
} from '#angular/http';
import {
IUser
} from './user';
import {
Observable
} from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
private _productUrl = 'Home/GetAllProducts';
constructor(private _http: Http) { }
getProducts(): Observable<IUser[]> {
return this._http.get(this._productUrl)
.map((response: Response) => <IUser[]>response.json().value)
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Stuck in this, any links available in google doesn't correctly solve my issue.
Please guide.
Thanks
You have mentioned _productUrl as your API path, but it should be actual API URL with domain name and action call.
as :
private _productUrl = 'localhost:50962/products/';
Eg.
Service.ts
import { Injectable } from '#angular/core';
import { Http, Response, RequestOptions,Request, RequestMethod, Headers } from '#angular/http';
import { IUser } from './user';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
private _productUrl = 'localhost:50962/products/';
constructor(private _http: Http) { }
getProducts(): Observable<IUser[]> {
let header = this.initHeaders();
let options = new RequestOptions({ headers: header, method: 'get' });
return this._http.get(this._productUrl + 'getAllProducts', options)
.map((response: Response) => <IUser[]>response.json().value)
.catch(this.handleError);
}
private initHeaders(): Headers {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Access-Control-Allow-Origin', '*');
return headers;
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
Also you can set environment variable for your API and use it in all your services. environment.API
export const environment = {
API: 'http://localhost:50962/',
WordPressAPI: 'http://localhost:58451/',
FacebookClientId: '45******',
}
return this._http.get(environment.API + 'products/getAllProducts', options)
.map((response: Response) => <IUser[]>response.json().value)
.catch(this.handleError);
You can use ngFor and the AsyncPipe
<div *ngFor="let user of getProducts() | async">
{{user.Id}}
{{user.ProductName}}
{{user.ProductPrice}}
</div>
A combination from both (use full path) Amol Bhor & Leon, and instead has the uri vars into env file use constants.ts file because for me environment is related to dev or prod environments. And to avoid memory leaks use asyn pipe, if not use unsubscribe into onDestroy method. Check docs for detail info.