I have created an api using ASP .net WebApi to get a list of companies and get a single company. Service call GetCompanies works fine gets the data and prints the list. But, issues is with GetCompany service, it gets the company when I print it in log, but it does not get in the Company object. What am I doing wrong in the Angular Component and or Service. Any help is appreciated.
Here is the output of the application. GetCompanies lists all the companies, but GetCompany prints as [object Object]. . here is the output
Here is the screen shot of data coming from APIs.
This is companies.component.ts
import { Component, OnInit } from '#angular/core';
import { CompaniesService } from './companies.service';
import { Company } from './company.model';
#Component({
selector: 'app-companies',
template: `
<p>
company name = {{company}}
</p>
<ul>
<li *ngFor = "let c of companies"> {{c.Name}} - {{c.CompanyID}} </li>
</ul>
`
})
export class CompaniesComponent implements OnInit {
text: string;
errorMessage: string;
public company: Company;
public companies: Company[];
constructor(private cService: CompaniesService) { }
ngOnInit() {
this.getCompanies();
this.getCompany(5);
console.log(this.company);
}
getCompanies() {
return this.cService.getCompanies()
.subscribe(companies => this.companies = companies,
error => this.errorMessage =<any>error);
}
getCompany(id: number) {
return this.cService.getCompany(id)
.subscribe(company => this.company = company,
error => this.errorMessage =<any>error);
}
}
This is companies.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions } from '#angular/http';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Company } from './company.model';
#Injectable()
export class CompaniesService {
constructor(private http: Http) {
}
getCompany(id: number): Observable<Company> {
return this.http.get(`api/getcompany/?id=${id}`)
.map ((res:Response) => res.json() )
.catch(this.handleError) ;
}
getCompanies(): Observable<Company[]> {
return this.http.get('api/getcompanies')
.map ((res:Response) => res.json() )
.catch(this.handleError) ;
}
private extractData(res: Response) {
let body = res.json();
return body.data || [];
}
private handleError (error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
code of company.model.ts
export class Company {
CompanyID: number;
Name: string;
Description: string;
EmailAddress: string;
Phone: string;
Address: string;
CreatedBy: number;
CreatedDate: Date;
UpdatedBy: number;
UpdatedDate: Date;
IsActive: boolean;
}
As you get data asynchronously you can use safe navigation operator like:
{{ company?.Name }}
Related
I am working with FirestoreDocument and I am trying to retrieving document data.I am getting the post undefined.Below is my code for service and Component
PostService.ts
import { Injectable } from '#angular/core';
import { AngularFirestore,AngularFirestoreCollection,AngularFirestoreDocument} from 'angularfire2/firestore'
import {Post} from './post';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
#Injectable()
export class PostService {
postsCollection: AngularFirestoreCollection<Post>
postDoc: AngularFirestoreDocument<Post>
constructor(private afs:AngularFirestore) {
this.postsCollection = this.afs.collection('posts',ref => ref.orderBy('published','desc'));
}
getPosts(){
return this.postsCollection.snapshotChanges().map(actions=>{
return actions.map(a=>{
const data=a.payload.doc.data() as Post
const id=a.payload.doc.id
return {id, ...data}
})
})
}
getPostData(id: string){
this.postDoc=this.afs.doc<Post>(`posts/${id}`)
return this.postDoc.valueChanges()
}
}
PostDetailComponent.ts
import { PostService } from './../post.service';
import { Component, OnInit } from '#angular/core';
import {ActivatedRoute} from '#angular/router';
import {Post} from '../post';
#Component({
selector: 'app-post-detail',
templateUrl: './post-detail.component.html',
styleUrls: ['./post-detail.component.css']
})
export class PostDetailComponent implements OnInit {
post: Post
constructor(
private route:ActivatedRoute,
private postService:PostService
) { }
ngOnInit() {
this.getPost();
console.log(this);
}
getPost(){
const id= this.route.snapshot.paramMap.get('id')
return this.postService.getPostData(id).subscribe(data=>this.post=data)
}
}
PostDetailComponent from console
PostDetailComponent {route: ActivatedRoute, postService: PostService}
post:undefined
postService:PostService {afs: AngularFirestore, postsCollection: AngularFirestoreCollection, postDoc: AngularFirestoreDocument}
route:ActivatedRoute {url: BehaviorSubject, params: BehaviorSubject, queryParams: BehaviorSubject, fragment: BehaviorSubject, data: BehaviorSubject, …}
__proto__:Object
My post from PostDetailComponent is undefined.
The rest of your code looks right, I think it's just that your console.log(this) is in the wrong spot.
ngOnInit() {
this.getPost(); <----- your getPost() function is asynchronous
console.log(this); <----- meaning this console.log runs before you get data from Firebase
so when this runs, posts is still undefined.
If you would console.log(this) *AFTER* you get data
from Firebase, then you should see the values OK.
}
getPost(){
const id= this.route.snapshot.paramMap.get('id')
return this.postService.getPostData(id).subscribe(data=>this.post=data)
^^^^^^^^^^^
ASYNC portion is right here
}
To fix it, move your console.log inside your subscription:
ngOnInit() {
this.getPost();
<--- From here
}
getPost(){
const id= this.route.snapshot.paramMap.get('id')
return this.postService.getPostData(id).subscribe(data=> {
this.post=data;
console.log(this); <--- To here
});
}
EDIT - Additional troubleshooting ref comments below.
getPost(){
const id= this.route.snapshot.paramMap.get('id')
console.log('id from route params is: ' + id); <---- log the *id* too
return this.postService.getPostData(id).subscribe(data=> {
this.post=data;
console.log(data); <--- log *data* instead
});
}
Since angular 6 there were changes on rxjs
// replace import 'rxjs/add/operator/map';
with import { map } from 'rxjs/operators';
Then include .pipe() inside PostService.ts file in getPosts() function
like this:
getPosts() {
return this.postCollection.snapshotChanges().pipe(map(actions => {
return actions.map( a => {
const data = a.payload.doc.data() as Post
const id = a.payload.doc.id
return { id, ...data }
})
})
)
}
Home someone helps, cheers !!!
Here i know hou to use http service in this way but how can i write service when its in function Like
export class studentController {
GetStudentData() {
constructor(http: Http) {
http.get('api/Employee').subscribe(result => {
this.student = result.json();
})
}
}
export class StudentMastre {
stdID: Number;
stdName: string;
email: string;
Phone: string;
Address: string;
}
You need to make a service to request the data and get, then use the service inside the component to get the data,
Your sample service should be,
#Injectable()
export class CategoryService {
constructor(private http: Http) { }
c(): Observable<StudentMastre[]> {
let wikiUrl = return this.http
.get('api/Employee')
.map(this.extractData)
.catch(this.handleErrors);
}
private extractData(res: Response) {
let data = res.json();
return data;
}
private handleErrors (error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
then in your component,
this.sampleService.
this.categoryService.getCategoriesService().subscribe(students=> {
this.students= students;
}, error => this.errorMessage = error);
I'm trying to make http call and if there will be any error do my things.
Here is my code:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
// Operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class HttpCallService {
constructor(private http: Http) { }
getHeroes(): Observable<Hero[]> {
console.log('entered');
return this.http.get('Url')
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
console.log('extract entered');
let body = res.json();
return body.data || {};
}
private handleError(error: Response | any) {
console.log('error entered');
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
export class Hero {
constructor(
public id: Date,
public author: string,
public text: string
) { }
}
When I call it it logs in console only entered which is in getHeroes. I know there will be error I haven't valid url but why it doesn't go to catch?
You need to invoke the subscribe() method to make actual HTTP call. Your method getHeroes() just declares that it'll return the Observable when someone will subscribe to it. That's why you only see the log from getHeroes() - extractData() and handleErrors() are not even invoked.
You need to do getHeroes().subscribe() somewhere in your code.
I'm getting the following error: Uncaught TypeError: result.subscribe is not a function
Here is also a screenshot of the error:
But I did tried to catch the error. Below you can see my code.
login.component.ts:
import { Component } from '#angular/core';
import { UserService } from '../../services/user.service';
import { User } from '../../models/user';
import {ToasterContainerComponent, ToasterService, ToasterConfig} from 'angular2-toaster/angular2-toaster';
#Component({
moduleId: module.id,
selector: 'login',
directives: [ToasterContainerComponent],
templateUrl: 'login.component.html',
providers: [UserService, ToasterService]
})
export class LoginComponent {
user: User = new User();
loginRes: String;
private toasterService: ToasterService;
public toasterconfig: ToasterConfig = new ToasterConfig({
showCloseButton: true,
tapToDismiss: false,
timeout: 0
});
constructor(private _userService: UserService, toasterService: ToasterService) {
this.toasterService = toasterService;
}
data = {};
onSubmit() {
this._userService.login(this.user)
.subscribe(
res => {
console.log("res onSubmit");
console.log(res);
},
function(error) { console.log("Error happened" + error)}
);
}
}
user.service.ts:
import { Injectable } from '#angular/core';
import { Headers, RequestOptions, Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { User } from '../models/user';
#Injectable()
export class UserService {
private loginUrl: string;
constructor(private _http: Http) {
}
login(user: User) {
this.loginUrl = "http://localhost:3000/api/auth/login";
let data = { "username": user.username, "password": user.password };
let body = JSON.stringify(data);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.post(this.loginUrl, body, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: any) {
console.log('Yup an error occurred', error);
return error.message || error;
}
}
As you can see I have tried to catch the error in the login() method in user.service.ts. Anyone that maybe knows how I can
solve this?
Your handleError() function needs to return an Observable
If you look at the HTTP Client Angular 2 docs there is an example, but for your specific case
Replace
private handleError(error: any) {
console.log('Yup an error occurred', error);
return error.message || error;
}
with
private handleError(error: any) {
console.log('Yup an error occurred', error);
return Observable.throw(error.message || error);
}
I'trying to use the HTTP service in Angular2 and i have some concerns.
I'm taking meteo datas from openweather API and I just want to put it inside a typeScript variable (meteo: {}) and use it as i want in my template.
Here are my .ts files:
meteo.service.ts
import {Injectable} from "angular2/core";
import {Http, Response} from "angular2/http";
import {Observable} from "rxjs/Observable";
import {MeteoComponent} from "../widgets/meteo/meteo.component";
import {Meteo} from "../widgets/meteo/meteo";
#Injectable()
export class MeteoService {
constructor(private http: Http) {}
// Nom de la ville sans accent
private _ville = 'Montreal';
// Initiales du pays
private _country = 'ca';
// Units (metric/imperial)
private _units = 'metric';
// API KEY
private _APPID = 'ewfw54f5646';
// url to get data
private _meteoUrl = 'http://api.openweathermap.org/data/2.5/weather?q='+this._ville+','+this._country+'&units='+this._units+'&APPID='+this._APPID;
getMeteo (): Observable<Meteo> {
return this.http.get(this._meteoUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
if(res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body = res.json();
return body || { };
}
private handleError(error: any) {
let errMsg = error.message || 'server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
meteo.component.ts
import {Component, OnInit, OnChanges, AfterContentInit} from "angular2/core";
import {MeteoService} from "../../services/meteo.service";
import {Meteo} from "./meteo";
#Component({
selector: 'meteo',
templateUrl: 'dev/widgets/meteo/meteo.component.html',
providers: [MeteoService]
})
export class MeteoComponent implements OnInit {
errorMessage: string;
meteo: Meteo;
// We inject the service into the constructor
constructor (private _meteoService: MeteoService) {}
// Instantiate data in the ngOnInit function to keep the constructor simple
ngOnInit() {
this.getMeteo();
}
getMeteo() {
this._meteoService.getMeteo()
.subscribe(
data => this.meteo = data,
error => this.errorMessage = <any>error);
}
}
meteo.ts
export class Meteo {
data: {};
}
and meteo.component.html
<span class="meteo">{{meteo | json}}°C</span>
Actually the result is the entire json object:
{
"coord": {
"lon":-73.59,
"lat":45.51
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04d"
}
],
"base":"cmc stations",
"main":{
"temp":3.96,
"pressure":1020,
"humidity":32,
"temp_min":2,
"temp_max":6.67
},
"wind":{
"speed":2.1
},
"clouds":{
"all":75
},
"dt":1461594860,
"sys":{
"type":1,
"id":3829,
"message":0.004,
"country":"CA",
"sunrise":1461577807,
"sunset":1461628497
},
"id":6077243,
"name":"Montreal",
"cod":200
}
And I would like to display just the temp field.
If you have any idea guys it's welcomed!
Thanks a lot.
You could leverage the Elvis operator since your data are loaded asynchronously:
<span class="meteo">{{meteo?.main.temp | json}}°C</span>
Try setting the data on this.meteo.data
getMeteo() {
this._meteoService.getMeteo()
.subscribe(
data => this.meteo.data = data,
error => this.errorMessage = <any>error);
}
and then displaying it with
<span class="meteo">{{meteo.data.main.temp}}°C</span>