Angular 4 Display Elements from a Promise - json

I have the following Typescript service (app.component.ts):
import { Component, OnInit } from '#angular/core';
import { ApiService } from './shared/api.service';
import {PowerPlant} from './shared/models/powerplant.model';
import 'rxjs/add/operator/toPromise';
#Component({
selector: 'app-root',
providers: [ApiService],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
// represents the URL's
allPowerPlantsURL = 'powerPlants';
// represents the data
powerPlants: PowerPlant[];
ngOnInit(): void {
this.allPowerPlants();
}
constructor(private apiService: ApiService) {
}
allPowerPlants(onlyActive: boolean = false, page: number = 1): void {
const params: string = [
`onlyActive=${onlyActive}`,
`page=${page}`
].join('&');
const path = `${this.allPowerPlantsURL}?${params}`;
this.apiService.get(path)
.toPromise()
.then(elem => {
console.log('In the allPowerPlants');
console.log(elem); **// prints undefined here**
this.powerPlants = <PowerPlant[]> elem; }
)
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
This is my app.component.html (just a snippet from it):
<div class="ui grid posts">
<app-powerplant
*ngFor="let powerPlant of powerPlants"
[powerPlant]="powerPlant">
</app-powerplant>
</div>
Now, in my powerplant.component.html, I have this:
import {Component, Input, OnInit} from '#angular/core';
import { PowerPlant } from '../shared/models/powerplant.model';
#Component({
selector: 'app-powerplant',
templateUrl: './powerplant.component.html',
styleUrls: ['./powerplant.component.css']
})
export class PowerplantComponent implements OnInit {
#Input() powerPlant: PowerPlant;
constructor() { }
ngOnInit() {
}
}
And finally, the one that is supposed to display the PowerPlant items are like this:
<div class="four wide column center aligned votes">
<div class="ui statistic">
<div class="value">
{{ powerPlant.powerPlantId }}
</div>
<div class="label">
Points
</div>
</div>
</div>
<div class="twelve wide column">
<div class="value">
MaxPower: {{ powerPlant.maxPower }} MinPower: {{ powerPlant.minPower }}
</div>
<div class="value">
MaxPower: {{ powerPlant.maxPower }} MinPower: {{ powerPlant.minPower }}
</div>
<div class="value">
PowerPlantType: {{ powerPlant.powerPlantType }} Organization: {{ powerPlant.powerPlantName }}
</div>
</div>
I can see that the server is sending me the array as the following console log on the get method shows:
get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
console.log('sending request to ' + `${environment.api_url}${path}`);
return this.http.get(`${environment.api_url}${path}`, { search: params })
.catch(this.formatErrors)
.map((res: Response) => {
console.log(res.json());
res.json();
});
}
Where the line console.log prints me the following as seen in the screenshot:
So why is the toPromise() fails? Just for information, this is how my PowerPlant model looks like:
export interface PowerPlant {
powerPlantId: number;
powerPlantName: string;
minPower: number;
maxPower: number;
powerPlantType: string;
rampRateInSeconds?: number;
rampPowerRate?: number;
}

Is there a specific reason to use the toPromise() method ? Does it work when subscribing normally ?
Try changing this
this.apiService.get(path)
.toPromise()
.then(elem => {
console.log('In the allPowerPlants');
console.log(elem); **// prints undefined here**
this.powerPlants = <PowerPlant[]> elem; }
)
to this :
this.apiService.get(path).subscribe(result => {
console.log('Im the result => ', result);
this.powerPlants = <PowerPlant[]> result;
});
Then it might be because you don't return the parsed result in your .map() method and thus you can't get the response in your promise / subscription.
.map((res: Response) => res.json()); // return is inferred in this syntax
.map((res: Response) => {
return res.json(); // here it's not
});

It is related to you your ApiService, you forgot to return res.json in your .map
get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
console.log('sending request to ' + `${environment.api_url}${path}`);
return this.http.get(`${environment.api_url}${path}`, { search: params })
.catch(this.formatErrors)
.map((res: Response) => {
console.log(res.json());
return res.json();
});
}

Related

Angular 13 Parent-Child not Communicating

Trying to get an array from a parent component to a child component. The Angular docs make it look really simple but I'm not sure what I'm doing wrong. The variable is activePost. Angular version is 13
Parent ts file (HomepageComponent):
import { Component, OnInit } from '#angular/core';
import { PostService } from 'src/app/services/post.service';
import { map } from 'rxjs/operators';
import { Post } from 'src/app/models/post.model';
import { ActivatedRouteSnapshot, Router } from '#angular/router';
import { PostDisplayComponent } from '../components/post-display/post-display.component';
#Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.scss']
})
export class HomepageComponent implements OnInit {
posts?: Post[];
category?:'';
currentpost?: Post;
currentIndex = -1;
title = '';
content='';
activePost: Post;
images: string[] =["../assets/img/damwon.jpg",
"../assets/img/FPX.jpg",
"../assets/img/2015skt.webp",
"../assets/img/2017SSG.webp",
"../assets/img/2014SSW.webp",
"../assets/img/TPA.webp",
"../assets/img/Fnatic.webp"]
backgroundImage: string = '';
constructor(private PostService: PostService,
private route: Router) { }
ngOnInit() {
let ran = Math.floor(Math.random()*6);
console.log(ran, Math.random()*100)
this.backgroundImage = this.images[ran];
this.retrieveposts();
}
refreshList(): void {
this.currentpost = undefined;
this.currentIndex = -1;
this.retrieveposts();
}
retrieveposts(): void {
this.PostService.getAll().snapshotChanges().pipe(
map(changes =>
changes.map(c =>
({ id: c.payload.doc.id, ...c.payload.doc.data() })
)
)
).subscribe(data => {
this.posts = data;
});
}
setActivepost(post: Post, index: number): void {
this.currentpost = post;
this.currentIndex = index;
console.log("Post:", post, "Index:", index);
this.activePost = this.currentpost
this.route.navigate(['/Read/'])
}
}
Child ts file (post-display component)
import { Component, OnInit, Input, OnChanges, Output, EventEmitter } from '#angular/core';
import { Post } from 'src/app/models/post.model';
import { PostService } from 'src/app/services/post.service';
import { HomepageComponent } from 'src/app/homepage/homepage.component';
#Component({
selector: 'app-post-display',
templateUrl: './post-display.component.html',
styleUrls: ['./post-display.component.scss']
})
export class PostDisplayComponent implements OnInit {
#Input() activePost: Post;
#Output() refreshList: EventEmitter<any> = new EventEmitter();
currentPost: Post = {
title: '',
description: '',
category:'',
published: false,
content: ''
};
message = '';
constructor(private PostService: PostService) { }
ngOnInit(): void {
console.log(this.activePost)
}
}
Child HTML:
<div class="container" style="padding-top: 200px;">
<div class="post">
ACTIVE POST HERE:
{{activePost}}
</div>
Looking at the console, the child component always returns undefined for activePost. I'm not sure if this is because I dont have anything in the parent html code for the child to look at? I feel like I should just be able to do this in the .ts file.
Help would be appreciated. Let me know if there are other project docs I should share as well.
Edit, added parent html:
<header class="header" [ngStyle]="{'background-image': 'url(' + backgroundImage + ')'}">
<div class="content">
<h1 class="heading">
<span class="small">Samsite:</span>
Stat
<span class="no-fill">check</span>
</h1>
<!--write a blog-->
</div>
</header>
<section class="blogs-section">
<div class="blog-card"
*ngFor="let post of posts; let i = index"
>
<h1>Title: {{ post.title }}</h1>
<h2> Category: {{ post.category }}</h2>
<p class="blog-overview"> Preview: {{ post.description }}</p>
<div class="btn" (click)="setActivepost(post, i)">Read!</div>
</div>
</section>

Angular 6 error: the data which I am getting from api is in the string format how to parse?

hi want to show the data from my api to my frontend (Angular 6) I am using HttpClient method from angular 6 I am new to angular
the data which I am getting from api is in the string format, I need to parse, below is the response image
this is model.ts
export interface Events {
IE_Incident_Start_Time: string;
IE_Start_time: string;
Title: string;
IE_Start_By: string;
Domain: string;
Impact: string;
IE_BU_Description: string;
}
this is component
enter code here
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { Incident } from '../../shared/incidents.model';
import { DataStorageService } from '../../shared/data-storage.service';
#Component({
selector: 'app-active-incident',
templateUrl: './active-incident.component.html',
styleUrls: ['./active-incident.component.css']
})
export class ActiveIncidentComponent implements OnInit {
incidents: Events[];
constructor(private router: Router, private dataStorageService:
DataStorageService) { }
ngOnInit() {
this.dataStorageService.getIncidents()
.subscribe(
(data: Events[]) => this.incidents = data,
(err: any) => console.log(err),
() => console.log('All done getting incidents')
);
}
this is service
enter code here
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Incident } from './incidents.model';
#Injectable()
export class DataStorageService {
constructor(private http: HttpClient) {}
getIncidents(): Observable<Events[]> {
console.log('Getting all incidents from server');
return this.http.get<Events[]>
('api/url');
}
}
html view
enter code here
<div class="card" *ngFor="let incident of incidents.Events">
<div class="card-header">
<span class="badge badge-danger"></span>{{incident.Title}}
<span class="badge badge-danger"></span>{{incident.Incident_Status}}
</div>
</div>
you can use the way as well
return this.dataStorageService.getIncidents()
.pipe(
map(jsonObj => Object.assign(new Events(), jsonObj),
catchError(error => console.log('Error!'))
);
Yes, you can do it this way.
this.dataStorageService.getIncidents().subscribe((data: Events[]) =>{
data.foreach(()=>{
this.incidents.push(JSON.parse(data));
})
},
(err: any) => console.log(err),
() => console.log('All done getting incidents')
);

Angular 4 - ERROR TypeError, ERROR CONTEXT DebugContext_

I'm rookie in Angular 4 and I need some help.
My code in console display error but in my template everything display correct.
Could someone help me understand what happend?
Error
ERROR TypeError: Cannot read property 'Tytul' of undefined
NewsDetailsComponent.html:7 ERROR CONTEXT DebugContext_ {view: Object, nodeIndex: 12, nodeDef: Object, elDef: Object, elView: Object}
news.ts
export interface News {
Ident: number;
Tytul: string;
Tresc: string;
Data: string;
}
news.service.ts
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import { News } from './news';
#Injectable()
export class NewsService {
private newsUrl = 'http://localhost:6128/getnews';
private headers = new Headers({ 'Content-type': 'application/x-www-form-urlencoded' });
private options = new RequestOptions({ headers: this.headers, withCredentials: true });
constructor(private http: Http) {}
getNews(): Promise<News[]> {
return this.http.get(this.newsUrl, this.options)
.toPromise()
.then(response => response.json().data as News[])
.catch(this.handleError);
}
getOneNews(id: number) {
const url = `${this.newsUrl}?Ident=${id}`;
return this.http.get(url, this.options)
.map(res => res.json());
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
news-details.component.ts
import { Component, Input, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { Location } from '#angular/common';
import 'rxjs/Rx';
import 'rxjs/add/operator/switchMap';
import { News } from './news';
import { NewsService } from './news.service';
#Component({
selector: 'app-news-details',
templateUrl: './views/news-details.component.html',
providers: [NewsService]
})
export class NewsDetailsComponent implements OnInit {
#Input() news: News;
constructor(
private newsService: NewsService,
private route: ActivatedRoute,
private location: Location
) {}
ngOnInit(): void {
this.route.params
.switchMap((params: Params) => this.newsService.getOneNews(+params['id']))
.subscribe(res => this.news = res);
}
goBack(): void {
this.location.back();
}
}
news-details.component.html
<section class="header-box">
<button class="header-btn back icon-wroc" (click)="goBack();"></button>
<div class="header-title">Komunikat</div>
</section>
<section class="content-box">
<h2>{{ news.Tytul }} </h2>
<div class="content-content" [innerHTML]="news.Tresc"></div>
</section>
You are doing request to service which probably get data from the server.
The problem is simple that while you are doing request to server your object is null but view is already generated you have two options
First
<h2>{{ news?.Tytul }} </h2>
Second
<section class="content-box" *ngIf="news">
<h2>{{ news.Tytul }} </h2>
<div class="content-content" [innerHTML]="news.Tresc"></div>
</section>
Fist option will generate empty h1 and div, second option will not generate anything untill news is not null

ngFor doesn't print JSON data

I'm developing an Angular2 application and I want to display some JSON data with http GET request from a JSON file.
Here's my JSON (file data/contatti.json):
[
"08823323459",
"3325849593",
"somemail#hotmail.com"
]
I have a ContactService that requests data from this file:
import { Injectable } from '#angular/core';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class ContattiService {
private contactUrl = 'data/contatti.json';
constructor(private http: Http) { }
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
getContatti(): Promise<string[]> {
return this.http.get(this.contactUrl)
.toPromise()
.then(res => res.json().data as string[])
.catch(this.handleError);
}
}
There is a component that retrieves the data using the service:
import { Component, OnInit } from '#angular/core'
import { ContattiService } from './contatti.service'
#Component({
selector: 'contact-app',
templateUrl: './contatti.html'
})
export class ContactComponent {
contatti: string[];
constructor(
private contactService: ContattiService) { }
ngOnInit(): void {
this.getContatti();
}
getContatti(): void {
this.contactService.getContatti().then(contatti => this.contatti = contatti);
}
}
But when I try to display them in my html page (contatti.html):
<div class="col-sm-6">
<div class="panel panel-default">
<ul>
<li *ngFor="let contatto of contatti">
{{contatto}}
</li>
</ul>
</div>
</div>
The page doesn't print data. Can someone help me please?
You should rewrite you method with subscribe:
getContatti(): void {
this.contactService.getContatti()
.subscribe(contatti => this.contatti = contatti);
}
and service to:
getContatti(): {
return this.http.get(this.contactUrl)
.map(res => res.json().data)
.catch(error => this.handleError(error));
}
And one more, if you try to access res.json().data your contatti.json should look like:
{
"data": [
"08823323459",
"3325849593",
"somemail#hotmail.com"
]
}
Try this inside the component,
getContatti(): void {
this.contactService.getContatti().subscribe(contatti=>{
this.contatti = contatti;
});
}
and service.ts should be,
getContatti(): {
return this.http.get(this.contactUrl)
.map(res => res.json().data)
.catch(error => this.handleError(error));
}

Display data from a json object array

I am unable to loop through a json object array and display all data in separate divs.
Currently just using some mock data.
Team.servie.ts:
import { Http } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '#angular/core';
import { Team } from './team';
#Injectable()
export class TeamService {
private _url = "http://jsonplaceholder.typicode.com/posts"
constructor(private _http: Http){
}
getPost() : Observable<Team[]>{
return this._http.get(this._url)
.map(res => res.json());
}
createPost(post: Team){
return this._http.post(this._url, JSON.stringify(post))
.map(res => res.json());
}
}
Component.ts:
import { Component, OnInit } from '#angular/core';
import { TeamService } from '../team.service';
#Component({
selector: 'About',
templateUrl: './about.component.html',
providers: [TeamService]
})
export class AboutComponent implements OnInit{
data;
isLoading = true;
constructor(private _teamService: TeamService){
/*this._teamService.createPost({userId: 1, title: "a", body: "b"});*/
}
ngOnInit(){
var text = "";
var i = 0;
this._teamService.getPost()
.subscribe(post => {
this.isLoading = false;
this.data = post;
console.log(post[0]);
});
}
}
Team.ts
export interface Team{
userId: number;
id?: number;
title: string;
body: string;
}
component.html:
<div *ngIf="isLoading">Getting data....</div>
<div let displayData of data>
<p> {{ displayData.id }}</p>
</div>
I know I am missing something, but i can't figure out what.
Any tips would be greatly appreciated.
use the *ngFor structureal directive like:
<div *ngFor="let displayData of data">
<p> {{ displayData.id }}</p>
</div>