Angular display single http response - json

I'm struggling by displaying data from a single JSON respone with angular.
I've created a class for the data interndata.model.ts
export class Interndata {
humidity: number;
temperature: number;
constructor(humidity:number, temperature:number) {
this.humidity = humidity;
this.temperature = temperature;
}
}
For this I crated a service interndata.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Interndata } from './interndata.model';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class InterndataService {
constructor(private http: HttpClient){}
public getDisplayData(): Observable<Interndata[]>{
return this.http.get<Interndata[]>('http://192.168.0.110:8080/process');
}
}
My JSON response from the webservice is this:
{"humidity": 49.099998474121094, "temperature": 24.899999618530273}
The class AppComponent shall get then the data regulary and update ngx-gauge to display the data.
import { Component, OnInit } from '#angular/core';
import { NgxGaugeModule } from 'ngx-gauge';
import { HttpClient } from '#angular/common/http';
import { concatMap, map, merge, switchMap, tap, delay, skip } from 'rxjs/operators';
import { concat, of, Observable, BehaviorSubject, timer } from 'rxjs';
import { Interndata } from './interndata.model';
import { InterndataService } from './interndata.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
interndata = new Array<Interndata>();
title = 'Home Automation Monitor Service';
tempValue = 0;
humValue = 0;
gaugeType = "semi";
tempLabel = "Temperatur";
tempAppendText = "°C";
gaugeThick = 25;
gaugeForegroundColor = "#000000";
gaugeBackgroundColor = "#FFFFFF";
tempMin = 0;
tempMax = 30;
humLabel = "Luftfeuchtigkeit";
humAppendText = "%";
humMin = 0;
humMax = 100;
constructor(private servinterdata : InterndataService){
servinterdata.getDisplayData().subscribe((res) => {
this.interndata = res;
console.log(this.interndata);
});
}
ngOnInit () {
}
}
I do not know how I can use the data from the JSON response. Console.log returns the JSON as string.
this.interndata.humidity
returns undefined. How can access the data I get from the JSON response?

If its returning a string, this.interndata = JSON.parse(res) should get you a nice javascript object. If that doesn't work, let me know and we can try something else.

public getDisplayData(): Observable<Interndata[]>
says to return an Observable of an Array of Interndata. This means that you have Typed the response as an array Interndata[] perhaps this is what you want but in that case the json must be an array like this.
[{"humidity": 49.099998474121094, "temperature": 24.899999618530273}]
and would be accessed like this:
this.interndata[0].humidity
To help debug this you can add an error handler like this
public getDisplayData(): Observable<Interndata[]> {
return this.http.get<Interndata[]>('http://192.168.0.110:8080/process')
.pipe<Interndata[]>(
catchError(err=>console.log('Err: '+err))
);
}
This is a good tutorial on Error Handling in RxJx: https://blog.angular-university.io/rxjs-error-handling/

Related

Angular 'Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.'

I'm creating an Angular app which shows list of projects and list of users from postgresql database, but I'm having issues with showing list of users in html.
The problem is that Angular is considering my array as an object no matter what I do.
The same code worked for projects but didn't work for users.
This is my service:
import { environment } from "../../../environments/environment";
import { Observable } from 'rxjs';
import { Projet } from '../modele/projet.model';
import { Test } from '../modele/test.model';
import { HttpParams,HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { map } from 'rxjs/operators';
import { User } from '../modele/user.model';
import { Financement } from '../modele/financement.model';
#Injectable()
export class WebService {
constructor(private httpClient: HttpClient) { }
serverUrl: string = "http://localhost:8080/"
get(url: string): Observable<any> {
return this.httpClient.get(this.serverUrl + url);
}
}
The component :
import { Component, OnInit } from '#angular/core';
import { User } from '../../shared/modele/user.model';
import { Router } from '#angular/router';
import { WebService } from '../../shared/sevices/web.service';
import { FormGroup, FormBuilder, FormControl, Validators, Form } from '#angular/forms';
#Component({
selector: 'app-show-users',
templateUrl: './show-users.component.html',
styleUrls: ['./show-users.component.scss']
})
export class ShowUsersComponent implements OnInit {
ngOnInit(): void {
this.getData();
}
usersList: Array<User>
user: User
myForm: FormGroup;
constructor(private webService: WebService, private formBuilder: FormBuilder,private router: Router) { }
getData(): void {
this.webService.get("showUsers").subscribe(res => {
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
})
}
}
The html :
<tr *ngFor="let user of usersList">
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
</tr>
This is the server response :
server response
NB: the EXACT same code worked for the object PROJECT
You need to make sure that the variable you pass into *ngFor is an array. You can make sure of this with Array.from(v) and can also strip any keys of an Object that might be sent from the serverside with Object.values(v):
this.webService.get("showUsers").subscribe(res => {
this.usersList = Array.from(Object.values(res.data.body.data));
})
In my case, I have a simple approach, but I spent a lot of time. You could try this:
datas: any;
this.token = JSON.parse(window.localStorage.getItem('token'));
this.authService.getData(this.token.id).subscribe(data => {
this.datas = data;
})
In the HTML template just use this.datas.id, this.datas.username instead of an *ngFor
You don't need this code:
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
simply use:
this.userlist = res
Youe complete method:
this.webService.get("showUsers").subscribe(res => {
this.userlist = res
});

Angular 2 api data

I want to get data from Riot API and display it in html view.
However, i can not "hold" this data in my variable. Console log show empty array.
I can see json data only in function scope.
I guess, i didn`t use observable function corretly, am i wrong?
Here is my component.
import { Component, OnInit } from '#angular/core';
import { FRIEND } from '../../services/_friends/mock-friends';
import { APIKEY } from '../../services/_lolapi/apikey';
import { Http, Response } from '#angular/http';
import { KeysPipe } from '../../pipes/key';
import { JsonPipe } from '#angular/common';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-friends',
templateUrl: './friends.component.html',
styleUrls: ['./friends.component.css']
})
export class FriendsComponent implements OnInit {
friends = FRIEND;
apikey = APIKEY;
nick: string[];
query: string;
private apiUrl =
'https://eun1.api.riotgames.com/lol/summoner/v3/summoners/by-name/';
data: Array<string> = [];
constructor(private http: Http) {
}
getFriendData(query) {
return this.http.get(query)
.map((res: Response) => res.json());
}
getContacts() {
this.getFriendData(this.query).subscribe(data => {
this.data = data;
console.log(this.data);
});
}
ngOnInit() {
for (let i of this.friends) {
this.query = `${this.apiUrl}${i.nick}${this.apikey}`;
this.getFriendData(this.query);
this.getContacts();
console.log(i.nick);
}
}
}
You don't need this.getFriendData(this.query) in ngOnInit as in the next line you call getContacts that wraps getFriendData.
Now, your API returns SummonerDTO - a complex object and you are trying to store it as an Array? That doesn't seem right.
Additionally, it think you want to store every result in an array, right?
In that case you should rather use:
this.data.push(data);

put the response of a service inside of a string variable with typescript

i'm working on an angular 4 project and i made a service to get a json from a url, the service.ts looks like this:
import {Injectable} from '#angular/core';
import {Http , Response} from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class EventsService{
constructor(private http:Http){
}
private url: string = "http://urlofmyjson/events";
getEvents() {
return (
this.http.get(this.url).map((response: Response) => response.json())
)
}
}
the content of that json looks like this:
{
"events":[
{
"title":"event1"
"location":"location1"
"date":"date1"
},
{
"title":"event2"
"location":"location2"
"date":"date2"
},
{
"title":"event3"
"location":"location3"
"date":"date3"
},
]
}
and in my component i have this:
import { Component, OnInit } from '#angular/core';
import {EventsService} from './conciertos.service';
#Component({
selector: 'app-events',
templateUrl: './events.component.html',
styleUrls: ['./events.component.scss']
})
export class EventsComponent implements OnInit {
constructor(private EventsService: ConciertosService) { }
events = []:
ngOnInit() {
this.EventsService.getEvents().subscribe( ResponseEvents => this.events=ResponseEvents);
}
}
and then i want to iterate each event of the json with an *ngFor, but as the json retrieves an object with an array inside of it that contains the events objects, i can't iterate it because it throws an error.
how can i put the response of the service inside a string type variable to call and iterate it with *ngFor?

Console.log to html element - Angular 4

Simple question. I have the following response from web service and I am observing it on chrome console. How do I deploy this onto Html element in angular 4? I tried to convert into JSON, but I encountered with another problem so I just decided to go with what I received after parseString.
All I want to do is, to display those fields in html element using Angular. For now, I just have component.ts file and trying to do something in html but can't figure out.
import { HttpClient, HttpErrorResponse, HttpHeaders } from '#angular/common/http';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { Observable } from 'rxjs/Observable';
import { RequestOptions, Response } from '#angular/http';
import { Injectable } from '#angular/core';
import { parseString } from 'xml2js'
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
//import { IMovie } from './movie';
#Injectable()
export class AppService {
private urlNorth = 'service';
constructor(private http: HttpClient) { }
getMovies(): Observable<any[]> {
const headers = new HttpHeaders();
headers.set('Content-Type', 'text/sml');
headers.set('Accept', 'text/xml');
headers.set('Content-Type', 'text/xml');
return this.http.get<any[]>(this.urlNorth, { headers })
.map(res => {
var result = res.text().replace('<string xmlns="service">', '').replace('</string>', '').replace(/</g, '<').replace(/>/g, '>');
parseString(result, (err, resultN) => {
if (err) {
return console.dir('invalid XML');
}
else {
console.log(resultN);
}
})
})
.catch(this.handleError);
}
private handleError(err: HttpErrorResponse): ErrorObservable {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
const errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
console.error(errorMessage);
return Observable.throw(errorMessage);
}
}
Log data
This code:
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
Does not belong in your service file. This is a component decorator and it should be on your component. Like this:
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private _appService: AppService) { }
getProduction() {
this._appService.getProduction()
}
}
Then your index.html file should use the tag to display the HTML.
In looking at your code more closely, there are other issues as well. For example, you are calling getProduction two times. You should not be calling it from the service constructor.
Also, the subscribe should be in the component, not the service.
And you should be using Http OR HttpClient, not both.
And TestBed is only for use in tests ... not in services.
I have a more complete example of a working component/service here: https://github.com/DeborahK/Angular-GettingStarted in the APM-Final folder. Consider looking through that code (or starting with that code) and making adjustments as needed for your application.
Here is a working service. (Without a plunker I can't successfully show this with your code. So you will need to make the appropriate replacements for your example.)
Service
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import { IMovie } from './movie';
#Injectable()
export class MovieService {
private moviesUrl = './api/movies/movies.json';
constructor(private http: HttpClient) { }
getMovies(): Observable<IMovie[]> {
return this.http.get<IMovie[]>(this.moviesUrl)
.do(data => console.log(JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(err: HttpErrorResponse): ErrorObservable {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
const errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
console.error(errorMessage);
return Observable.throw(errorMessage);
}
}
Component:
import { Component, OnInit } from '#angular/core';
import { IMovie } from './movie';
import { MovieService } from './movie.service';
#Component({
templateUrl: './movie-list.component.html',
styleUrls: ['./movie-list.component.css']
})
export class MovieListComponent implements OnInit {
movies: IMovie[];
errorMessage: string;
constructor(private movieService: MovieService) { }
ngOnInit(): void { this.getMovies(); }
getMovies(): void {
this.movieService.getMovies()
.subscribe(
(movies: IMovie[]) => this.movies = movies,
(error: any) => this.errorMessage = <any>error);
}
}

Load JSON data into Angular 2 Component

I am trying to load JSON hada into an Angular 2 Component, and I think I have found the way.
datoer.service.ts:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class DatoService {
dato: Array<any>;
constructor(private http: Http) {}
getDato() {
return this.http.request('./datoer.json')
.map(res => res.json());
}
}
kalender.component.ts:
import { Component } from '#angular/core';
import { ValgteSkolerService } from '../valgteSkoler.service';
import { DatoService } from './datoer.service';
#Component({
selector: 'kalender',
providers: [DatoService],
templateUrl: 'app/kalendervisning/html/kalender.html'
})
export class KalenderComponent {
private valgteSkoleRuter: Array<any>= [];
//private datoer: Array<any> = [];
constructor(private valgteSkolerService: ValgteSkolerService, private DatoService: DatoService) {
this.datoer = this.DatoService.getDato();
}
ngOnInit() {
this.valgteSkolerService.hentLagretData();
this.valgteSkoleRuter = this.valgteSkolerService.delteValgteSkoleRuter;
}
My template is like:
<p *ngFor="let dato of datoer"> {{dato}} </p>
My problem is the this.datoer above in the component. It says it does not exist on type KalenderComponent.
I have tried declaring it like this in the component:
private datoer: Array<any> = [];
But then it says that "Type 'Observable' is not assignable to type 'any[]'. Property 'length' is missing in type 'Observable'.
Any ideas how to solve this?
The http service, according to Angular2 Http class docs, returns an observable not an array with results, that's because it's made asynchronously. Therefore you must subscribe to the observable so you can feed your array when it gets notified (this happens when http request is complete).
For example:
public datoer: any[] = [];
constructor(
private valgteSkolerService: ValgteSkolerService,
private DatoService: DatoService) {
this.DatoService
.getDato()
.subscribe(datoer => { this.datoer = datoer; });
}