Angular 4 this.http.get(...).map is not a function - javascript

Hi i have problem with my code.
import { Injectable } from '#angular/core';
import { Car } from "./models/car";
import { Observable } from "rxjs/Observable";
import { Http } from "#angular/http";
import 'rxjs'
#Injectable()
export class CarsService {
private apiUrl = "http://localhost:3000/api/cars";
constructor(private http : Http) { }
getCars() : Observable<Car[]> {
return this.http.get(this.apiUrl)
.map((res) => res.json())
}
}
With this code i have error:
this.http.get(...).map is not a function
but when i add:
import 'rxjs/add/operator/map'
Still have problem but error is:
Cannot read property 'map' of undefined
Can you help me? Thanks

As mentioned by others Http is deprecated, use HttpClient instead. HttpClient parses your response to an Object, so you remove the mapping of the response. Also, to avoid type checking errors, tell Angular what kind of response you are expecting.
So import HttpClientModule and add it to imports array, after BrowserModule. In your Service import HttpClient, inject it in your constructor and use it the following way:
import { Injectable } from '#angular/core';
import { Car } from "./models/car";
import { Observable } from "rxjs/Observable";
import { HttpClient } from "#angular/common/http";
import 'rxjs'
#Injectable()
export class CarsService {
private apiUrl = "http://localhost:3000/api/cars";
constructor(private httpClient : HttpClient) { }
getCars() : Observable<Car[]> {
// tell Angular you are expecting an array of 'Car'
return this.httpClient.get<Car[]>(this.apiUrl)
}
}

With angular5 HttpClient implementation already includes inner using of the map.so it works for you automatically.
just update it as
getCars() : Observable<Car[]> {
return this.http.get(this.apiUrl)
}
Also make sure you are using HttpClient instead of Http.
You can read more about this here

Edit your code
import { Injectable } from '#angular/core';
import { Car } from "./models/car";
import { Observable } from "rxjs/Observable";
import { Http } from "#angular/http";
#Injectable()
export class CarsService {
private apiUrl = "http://localhost:3000/api/cars";
constructor(private http : Http) { }
getCars() : Observable<Car[]> {
return this.http.get(this.apiUrl)
}
}
since it automatically parse the response as JSON. You don't have to explicitly parse it.

ngOnInit() {
this.loadCars();
}
loadCars() : void {
this.carsService.getCars().subscribe((cars) => {
this.cars = cars;
this.countTotalCost();
})
}
So i move this this.countTotalCost();
from ngOnInit to loadCars
and now .map its ok.
I have only this error: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'NaN'.
<div class="row" *ngIf="grossCost"> //this line error/error context
<div class="col-sm-12">
<div class="total-cost">
<p class="text-right">TOTAL GROSS COST: {{ grossCost}} PLN</p>
</div>
</div>
</div>

Related

Angular 9 application "NgFor only supports binding to Iterables such as Arrays" error

I am working on a Contacts app with Angular 9. I get a list of contacts via the following service:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Contact } from '../models/Contact';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
}
#Injectable({
providedIn: 'root'
})
export class ContactsListService {
contactsUrl = 'https://randomuser.me/api/?&results=500&inc=name,location,email,cell,picture';
constructor(private http:HttpClient) { }
getContcts():Observable<Contact[]> {
return this.http.get<Contact[]>(`${this.contactsUrl}`);
}
}
The Contacts List component is as follows:
import { Component, OnInit } from '#angular/core';
import { from } from 'rxjs';
import { ContactsListService } from '../../services/contacts-list.service';
import { Contact } from '../../models/Contact';
#Component({
selector: 'app-list',
templateUrl: './list.component.html',
})
export class ListComponent implements OnInit {
contactsList:Contact[];
constructor(private ContactsListService:ContactsListService) { }
ngOnInit(): void {
this.ContactsListService.getContcts().subscribe(contactsList => {
this.contactsList = contactsList;
});
}
}
Trying to iterate the contacts list this way
<ul *ngFor="let contact of contactsList">
<li>{{contact.name.first}}</li>
</ul>
throws the error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
That very likely means contactsList is not an array.
What am I doing wrong?
The URL is returning an object of the form
{
results: [],
info: {}
}
Use RxJS map to map the results obtained from the API.
Service
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { pipe } from 'rxjs';
import { map } from 'rxjs/operators';
import { Contact } from '../models/Contact';
export class ContactsListService {
contactsUrl = 'https://randomuser.me/api/?&results=500&inc=name,location,email,cell,picture';
constructor(private http:HttpClient) { }
getContcts():Observable<Contact[]> {
return this.http.get<Contact[]>(`${this.contactsUrl}`)
.pipe(map(response => response['results']));
}
}
Assign empty array to contactsList on declaration.
Component
import { Component, OnInit } from '#angular/core';
import { from } from 'rxjs';
import { ContactsListService } from '../../services/contacts-list.service';
import { Contact } from '../../models/Contact';
#Component({
selector: 'app-list',
templateUrl: './list.component.html',
})
export class ListComponent implements OnInit {
contactsList: Contact[] = []; // assign empty array
constructor(private ContactsListService:ContactsListService) { }
ngOnInit(): void {
this.ContactsListService.getContcts().subscribe(
contactsList => { this.contactsList = contactsList; },
error => { // always good practice to handle error when subscribing to HTTP observables }
);
}
}
Seems like the endpoint 'https://randomuser.me/api/?&results=500&inc=name,location,email,cell,picture' does not return an array. To check it you may open it in the browser, or check in the network tab of the chrome developers tools while your app running

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined in Angular 7 and rxjx

I have recently upgraded my angular 2 app to angular 7. One of the challenges that I had was the user.service.ts where I have isAuthentiated method is. Basically, this method is passed into the auth.guard.ts so that I can direct users if their username is not on my list.
User Service retrieves the users then isAuthenticated checks the users. Auth guard is checking the user. If the user is in the list, grant access, otherwise navigate them to a certain website.
user.service.ts
import { Injectable } from '#angular/core';
import { environment } from '../../environments/environment';
import { map, catchError, tap } from 'rxjs/operators';
import { HttpClient } from '#angular/common/http';
import { Observable, of } from 'rxjs';
#Injectable()
export class UserService {
baseUrl = environment.apiUrl;
constructor(private http: HttpClient) { }
private extractData(res: Response) {
const body = res;
return body || { };
}
... other methods
isAuthenticated(): Observable<boolean> {
return this.http.get(this.baseUrl + 'users').pipe(
map(this.extractData),
map(res => !!res.length)
);
}
}
And my auth.guard.ts is:
import { UserService } from './../_services/user.service';
import { Injectable } from '#angular/core';
import { CanActivate, RouterStateSnapshot, Router } from '#angular/router';
import { AlertifyService } from '../_services/alertify.service';
import { map } from 'rxjs/operators';
#Injectable()
export class AuthGuard implements CanActivate {
constructor(
private userService: UserService,
private alertifyService: AlertifyService,
private router: Router
) {}
canActivate(route, state: RouterStateSnapshot) {
return this.userService.isAuthenticated().pipe(map(user => {
if (!user) {
return true;
} else {
this.router.navigate(['/authentication/get-jhed']);
this.alertifyService.error('You need to be authenticated to access this area');
return false;
}
}));
}
}
This code returns the following error:
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined
I tried res[0].length I didn't receive the error but nothing happened this time.
I am able to solve this issue using Http as below:
isAuthenticated(): Observable<boolean> {
return this.http.get(this.baseUrl + 'users').pipe(
map(res => res.json()),
map(res => !!res.length)
);
}
Please note that I use Http in here, NOT HttpClient.
Any help would be appreciated!
HttpClient by default indicates response body not a whole response object. If you migrate from Http to HttpClient at the same time - to be compatibile with the previous way - use options object to return whole response in callback.
isAuthenticated(): Observable<boolean> {
return this.http.get(this.baseUrl + 'users', { observe: 'response' }).pipe(
map(this.extractData),
map(res => !!res.length)
);
}

processing http call's response: filter is not a function

Provider code:
import {AutoCompleteService} from 'ionic2-auto-complete';
import { Http } from '#angular/http';
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import 'rxjs/add/operator/map';
#Injectable()
export class AutoSuggestProvider implements AutoCompleteService {
constructor(public http: HttpClient, public HTTP: Http) {
console.log('Hello AutoSuggestProvider Provider');
}
getResults(keyword:string) {
return this.HTTP.get("https://restcountries.eu/rest/v1/name/"+keyword) .map( result => { return result.filter(item => item.name.toLowerCase().startsWith(keyword.toLowerCase()) ) });
}
}
Problematic line:
return this.HTTP.get("https://restcountries.eu/rest/v1/name/"+keyword)
.map( result => { return result.filter(item =>
item.name.toLowerCase().startsWith(keyword.toLowerCase()) ) });
As you can see this is a problematic line it saying.
Property 'filter' does not exist on type 'Response'.
Please help me How can I solve this issue?
Please try this
import { Http } from '#angular/http'
import 'rxjs/add/operator/map';
getResults(keyword:string){
return this.Http.get("https://restcountries.eu/rest/v1/name/"+keyword).map(res=>{
return res.json()
}).map(fil=>{
return fil.filter(res=>{
return res.name.toLowerCase().startsWith(keyword.toLowerCase())
})
})
}
In first map return as json and in second map do a filter function to filter the result based on keyword

wordpress and angular theme update post list on when new post is published

Hi i'm new in Angular 4 and I want to use it to build a WordPress theme using the wp-api. I start with the ng-wp-theme but I and all its working fine, but I need that hen a new post is publish the post list page updates itself without reload the page. I saw some tutorials about the http services in angular but I dont find any solution to this, maybe its a Wordpress api issue and not the Angular part.
here is the service:
import { Injectable } from '#angular/core';
import { HttpClient } from "#angular/common/http";
import { Observable } from 'rxjs/Observable';
import { Post } from './post';
import { environment } from '../../environments/environment';
#Injectable()
export class PostsService {
private _wpBase = environment.wpBase;
constructor(private http: HttpClient) { }
getPosts(): Observable<Post[]> {
return this.http.get<Post[]>(this._wpBase + 'posts');
}
getPost(slug: string): Observable<Post[]> {
return this.http.get<Post[]>(this._wpBase + `posts?slug=${slug}`);
}
}
and the controller:
import { Component, OnInit } from '#angular/core';
import { Post } from '../post';
import { PostsService } from '../posts.service';
import { Router } from '#angular/router';
import { HttpErrorResponse } from '#angular/common/http';
#Component({
selector: 'app-post-list',
templateUrl: './post-list.component.html',
styleUrls: ['./post-list.component.css'],
providers: [PostsService]
})
export class PostListComponent implements OnInit {
public posts: Post[];
constructor( private postsService: PostsService, private router: Router ) {}
ngOnInit() {
this.postsService.getPosts().subscribe(
(posts: Post[]) => this.posts = posts,
(err: HttpErrorResponse) => err.error instanceof Error ? console.log('An error occurred:', err.error.message) : console.log(`Backend returned code ${err.status}, body was: ${err.error}`));
}
selectPost(slug) {
this.router.navigate([slug]);
}
}

TypeError: this.http.get(...).map is not a function

In my Angular 4 app I'm trying to get some data from an API. I'm using this article which explains how to do that, but I'm getting an exception:
TypeError: this.http.get(...).map is not a function
This is my code:
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import { Person } from '../../../interfaces/Person';
import {configuration} from "../config";
#Injectable()
export class AdsService{
private baseUrl: string = configuration.serverUrl;
constructor(private http : Http){
}
getAll(): Observable<Person[]>{
let people$ = this.http
.get(`${this.baseUrl}/people`, {headers: this.getHeaders()})
.map(mapPeople);
return people$;
}
}
function mapPeople(response:Response): Person[]{
return response.json().results;
}
Any help will be profoundly appreciated!
I dont see the map method imported.
Add this to your imports
import rxjs/add/operator/map
You must import map in this file, for that you just need to add the following line:
import 'rxjs/add/operator/map';
OR
import 'rxjs/add/operators/map';
Also, if you are using Angular 5 or above, then the above imports have been sorted to :
import { map } from 'rxjs/operator';
OR
import { map } from 'rxjs/operators';
Add this and Enjoy !!! :-)

Categories