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);
Related
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
});
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/
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?
I'm stuck here trying to loop the observable object on my users service.
The Chrome's console throws:
error_handler.js:47 EXCEPTION: undefined is not a function
Here's my code:
users.component.ts
import { Component, OnInit } from '#angular/core';
import { UserService } from '../user.service';
import { Observable } from 'rxjs/Rx';
import { User } from '../user';
#Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit {
people: Observable<User[]>;
constructor( private _userService: UserService) { }
ngOnInit() {
this.people = this._userService.getAll();
console.log(this.people);
}
}
users.service.ts
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { User } from './user';
#Injectable()
export class UserService {
private baseurl: string= 'http://swapi.co/api';
constructor(private http: Http) {
console.log("User service initialized");
}
getAll(): Observable<User[]>{
let users$ = this.http
.get(`${this.baseurl}/people`,{headers: this.getHeaders()})
.map(this.mapUsers);
return users$;
}
private getHeaders(){
let headers = new Headers();
headers.append('Accept', 'application/json');
return headers;
}
mapUsers(response: Response): User[]{
return response.json().results.map(this.toUser);
}
toUser(r:any): User{
let user = <User>({
id: this.extractId(r),
name: r.name
});
console.log('Parsed user'+user.name);
return user;
}
extractId(personData:any){
let extractedId = personData.url.replace('http://swapi.co/api/people/','').replace('/','');
return parseInt(extractedId);
}
}
users.component.html
<ul class="people">
<li *ngFor="let person of people | async " >
<a href="#">
{{person.name}}
</a>
</li>
</ul>
user.ts
export interface User{
id: number;
name: string;
}
When I remove the HTML code from the template, everything works great (no errors on console) so, I guess there's something wrong with 'people' object, and obviously I can't iterative the response. Please guys, a hand would be appreciated here.
The most likely reason is the way you are handling the map callback
getAll(): Observable<User[]>{
let users$ = this.http
.get(`${this.baseurl}/people`,{headers: this.getHeaders()})
.map(this.mapUsers);
}
mapUsers(response: Response): User[]{
return response.json().results.map(this.toUser);
}
toUser() {}
You need to be careful when using this inside callback functions. The context sometimes messes you up. In this case this in .map(this.toUser) does not point to the class instance. You need to bind it, i.e.
let users$ = this.http
.get(`${this.baseurl}/people`,{headers: this.getHeaders()})
.map(this.mapUsers.bind(this));
When you use bind(this) you are saying that any uses of this inside the mapUsers function should be bound to the class instance.
When you use arrow functions, you don't need to worry about this distinction, as it keeps the lexical scope context
let users$ = this.http
.get(`${this.baseurl}/people`,{headers: this.getHeaders()})
.map(res => response.json().results.map(this.toUser));
Also, even passing the toUser function has the same problem, as you are using this.extractId(r). You also need to bind that
mapUsers(response: Response): User[]{
return response.json().results.map(this.toUser.bind(this));
}
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; });
}