I am trying to get my JSON response from the HttpClient service into an array so that I can loop through using *ngFor in my html. I've tried using "this" to loop through but *ngFor will not accept it. Below is the code for my service.ts component and the main component.ts.
I just need some way to convert an array from "resp.body" into an exportable Array to be used for string interpolation in the html. Any help would be much appreciated!
races.component.ts
import { Component, OnInit } from '#angular/core';
import {Race, RacesService} from './races.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'dh-races',
templateUrl: './races.component.html',
providers: [ RacesService ],
styleUrls: ['./races.component.scss']
})
export class RacesComponent {
error: any;
headers: string[];
race: Race;
raceM: any[];
constructor(private racesService: RacesService) {
var raceM = [];
var raceArray = [];
this.racesService.getRaceResponse()
.subscribe(resp => {
raceArray.push(resp.body);
for (let obj of raceArray) {
for (let i in obj) {
raceM.push({
"ID": obj[i].id + ",",
"Date": obj[i].activityStartDate,
"RaceName": obj[i].assetName,
"Website": obj[i].website
})
}
console.log(raceM);
return raceM;
}
});
}
races.service.ts
#Injectable()
export class RacesService {
constructor(private httpClient: HttpClient) { }
getRace() {
return this.httpClient.get(activeApiURL).pipe(
retry(3),
catchError(this.handleError)
);
}
getRaceResponse(): Observable<HttpResponse<Race>> {
return this.httpClient.get<Race>(
activeApiURL, {
observe: 'response'
});
}
To fix the issue, you need to create an interface that matches the data you get from the server, I will call this interface IRace.
Then in the component I will create a variable named races, I will assign the returned value from the server response i.e. resp.body to the races variable.
I'd change the service to look like this:
export interface IRace {
// Your response from server object's properties here like so:
id: Number;
assetName: string;
...
}
export class RacesService {
constructor(private httpClient: HttpClient) { }
getRace() {
return this.httpClient.get(activeApiURL).pipe(
retry(3),
catchError(this.handleError)
);
}
getRaceResponse(): Observable<HttpResponse<Array<Race>>> {
return this.httpClient.get<Array<Race>>(
activeApiURL, {
observe: 'response'
});
}
}
Finally, I'd change the race component to this:
import { Component, OnInit } from '#angular/core';
import { Race, RacesService, IRace } from './races.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'dh-races',
templateUrl: './races.component.html',
providers: [ RacesService ],
styleUrls: ['./races.component.scss']
})
export class RacesComponent {
error: any;
headers: string[];
races: IRace[];
constructor(private racesService: RacesService) {
this.racesService.getRaceResponse()
.subscribe(resp => {
this.races = resp.body;
});
}
}
I hope this helps.
Related
Please help on the below issue this is my model class. I tried all the possible ways using .pipe.map() import {map} from rxjs/operators method, but still giving [object Object]
export class AppProfilesDetailsDO {
envName?: string;
envDesc?: string;
envIpAddress?: string;
envProfileName?: string;
envCrDeployed?: string;
envUrl?: string;
envAdminConsoleUrl?: string;
envDbSchema?: string;
envDbUserId?: string;
envGisSchema?: string;
envPortNo?: number;
}
my component class
import { Component, OnInit } from '#angular/core';
import { ProfileserviceService } from './profileservice.service';
import { AppProfilesDetailsDO } from '../models/AppProfilesDetailsDO';
#Component({
selector: 'app-profiledetails',
templateUrl: './profiledetails.component.html',
styleUrls: ['./profiledetails.component.css']
})
export class ProfiledetailsComponent implements OnInit {
appProfileData: AppProfilesDetailsDO[];
constructor(private profileService: ProfileserviceService) { this.appProfileData = [] }
ngOnInit() {
console.log("In profiledetails component");
this.profileService.getProfileSetUpDetails().subscribe(
appProfileData => {
this.appProfileData = appProfileData;
}
);
console.log("Compenent Profile Data: "+this.appProfileData); ==> **in my console it is
printing as ==> [object Object] **
}
}
My service component
import { HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { AppProfilesDetailsDO } from "../models/AppProfilesDetailsDO";
#Injectable({
providedIn: 'root'
})
export class ProfileserviceService {
BASE_PATH:string = "http://localhost:8080/getProfileSetUpDetails";
constructor(private httpClient: HttpClient) {}
httpOptions = {
headers: new Headers ({
'Content-type': 'application/json'
})
}
appProfileData?: AppProfilesDetailsDO[];
getProfileSetUpDetails() : Observable<AppProfilesDetailsDO[]> {
return this.httpClient.get<AppProfilesDetailsDO[]>(this.BASE_PATH);
}
}
I am not sure where it is wrong. Please help on this issue.
Thanks.
The problem is this line console.log("Compenent Profile Data: "+this.appProfileData);. You are trying to concatenate an object with a string.
Simply change that line to console.log("Compenent Profile Data: ", this.appProfileData);
For more clarity look at this example:
var data = { a: "ali" };
console.log("Compenent Profile Data: " , data); console.log("Compenent Profile Data: " + data);
If you want to see the result it should be like this
console.log("Component Profile Data:", this.appProfileData);
other ways it will try to log the concatenated value of string with the result object which is impossible
You can not impose concatenation in between string and an array of object as you did like this:
console.log("Compenent Profile Data: "+this.appProfileData);
So, just use like this instead and problem will be gone:
console.log(this.appProfileData);
EDIT: I made changes in the push method but it still did not work
I am making get request to an api and pushing each of the responses to an array. The array is visible when logged to console. On printing the length of the array in the template length comes out to be 5. But when I try to iterate through it using ngFor no output is being displayed
Service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import {Quote} from 'src/app/models/quote';
#Injectable({
providedIn: 'root'
})
export class StockpriceService {
url1='https://financialmodelingprep.com/api/v3/quote-short/';
url2='?apikey=efa24b272821b542c459557332c02a1e';
constructor(private http:HttpClient) {
}
//alpha apikey="VETRGM94G70WQGX9";
getQuote(symbol:string) //load data from api
{
return this.http.get<Quote>(this.url1 + symbol + this.url2);
}
}
ts file
import { Component, OnInit } from '#angular/core';
import{Quote} from 'src/app/models/quote';
import{StockpriceService} from 'src/app/services/stockprice.service';
import { timer } from 'rxjs';
#Component({
selector: 'app-stocks',
templateUrl: './stocks.component.html',
styleUrls: ['./stocks.component.css']
})
export class StocksComponent implements OnInit {
stocks: Array<Quote>=[];
symbols=['AAPL', 'GOOG', 'FB', 'AMZN', 'TWTR'];
constructor(private serv:StockpriceService) { }
ngOnInit(): void {
this.symbols.forEach(symbol => {
this.serv.getQuote(symbol).subscribe(
(data:Quote)=>{
console.log(data);
this.stocks.push(
{
symbol:data.symbol,
price:data.price,
volume:data.volume
}
);
}
)
});
console.log('stocks array is')
console.log(this.stocks);
}
}
Template
<div *ngFor="let stock of stocks">
{{stock.symbol}}
{{stock.price}}
</div>
sample api response
[ {
"symbol" : "AAPL",
"price" : 126.81380000,
"volume" : 36245456
} ]
Accordingly I have an interface defined for it as
export interface Quote{
symbol:string;
price:number;
volume:number;
}
This will work fine.
this.serv.getQuote(symbol).subscribe((data: Quote[]) => {
console.log(data);
this.stocks.push(...data);
});
I have a class Projects
export class Projects {
project_id: number;
project_name: string;
category_id: number;
project_type: string;
start_date: Date;
completion_date: Date;
working_status: string;
project_info: string;
area: string;
address: string;
city: string;}
Its Service class is
#Injectable()
export class ProjectsService {
constructor(private http: HttpClient) {}
//http://localhost:9090/projectInfo
private apiUrl = 'http://localhost:9090/projectInfo';
public findAll() {
return this.http.get(this.apiUrl);
}
getProducts(): Observable<ProjectsModule[]> {
return this.http.get<ProjectsModule[]>(this.apiUrl);
}
Component is
import { Component, OnInit } from '#angular/core';
import { ProjectsService } from '../projects.service';
import{Projects} from '../projects';
import { plainToClass, Transform, Expose, Type, Exclude } from 'class-transformer';
#Component({
selector: 'app-project-list',
templateUrl: './project-list.component.html',
styleUrls: ['./project-list.component.css'],
providers: [ProjectsService]
})
export class ProjectListComponent implements OnInit {
private projects:Projects[]=[];
stringObject: any;
constructor(
private projectsService: ProjectsService) { }
vandana='rahul';
ngOnInit() {
this.getAllProjects();
}
getAllProjects() {
this.projectsService.getProducts().subscribe((data: Projects[])=> {
this.stringObject =JSON.stringify(data)
let newTodo = Object.assign(new Projects(), data);
this.projects= <Projects[]>this.stringObject;
console.log("data -"+ this.projects)
console.log("Array -"+ this.stringObject)
console.log("data -"+ this.projects[1].project_info)
},
err => {
console.log(err);
}
);
}
When i am trying to read newTodo.project_id (or any property of class Projects) it is undefined
but newtodo is returning jsondata
output is
Please help me in getting values newtodo.project_id, newtodo.project_name and so on
You're assigning a JSON string to this.projects.
The JSON string is [{"projectId": 1, ... }].
So:
this.projects[1] evaluates to { (i.e. the second character in the string)
"{".project_id evaluates to undefined
You should assign the data itself to this.projects:
this.projects = data;
And then keep in mind that arrays in JavaScript are zero-based. Since you only have one object in your array, you'd have to print the projectId as follows:
console.log(this.projects[0].projectId);
Also, the properties of your Projects class don't match your JSON at all. Furthermore, Projects should probably be named Project, and should be an interface instead of a class.
I know this question has been asked several times, but problem is that nobody tried to make a some fiddle or show results of code. This is what i have, i need to update values in other component based on value in some other component, but that is not just value,I have call function again in some other component.
I have some component that goes to database and update values, on second hand I have other component that read those values from database from service.
This is example of my code
tasks.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { environment } from '../../environments/environment';
import { Tasks } from './tasks';
#Injectable()
export class TasksProvider {
constructor(private http: HttpClient) { }
createNewTask(name: Name) : Observable<any> {
return this.http.post(environment.apiUri + 'tasks', { name, finished: false },
{ responseType: 'text' });
}
updateTask(id: Id, name: Name, finished: boolean) : Observable<any> {
return this.http.put(environment.apiUri + 'tasks/' + id, { name, finished },
{ responseType: 'text' });
}
getAllTasks(): Observable<Tasks[]> {
return this.http.get(environment.apiUri + 'tasks')
.map<any, Tasks[]>(data => data.map(Tasks.fromObject));
}
}
app.component.html
<app-tasks-list></app-tasks-list>
<app-tasks-add-new></app-tasks-add-new>
As you may see I have not child components, that is my main problem
tasks-list.component.ts
import {Component} from '#angular/core';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
#Component({
selector: 'app-tasks-list',
templateUrl: './tasks-list.component.html',
styleUrls: ['./tasks-list.component.scss']
})
export class TasksListComponent {
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) { }
ngOnInit() {
this.getTasksList();
}
displayedColumns: string[] = ['id', 'name', 'finished'];
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
tasks-add-new.component.ts
import { Component, OnInit, Inject } from '#angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
export interface DialogData {
name: string;
}
#Component({
selector: 'app-tasks-add-new',
templateUrl: './tasks-add-new.component.html',
styleUrls: ['./tasks-add-new.component.scss']
})
export class TasksAddNewComponent implements OnInit {
ngOnInit() {
}
constructor(public dialog: MatDialog, private tasksProvider: TasksProvider) {}
openDialog(): void {
const dialogRef = this.dialog.open(TasksAddNewDialog, {
width: '250px',
data: {name: this.animal}
});
dialogRef.afterClosed().subscribe(result => {
this.name = result
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
}
#Component({
selector: 'tasks-add-new-dialog',
templateUrl: 'tasks-add-new-dialog.html'
})
export class TasksAddNewDialog {
constructor(
public dialogRef: MatDialogRef<TasksAddNewDialog>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
You see now when i call function in tasks-add-new.component.ts like
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
I need to call again function in tasks-list.component.ts
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
Does any body have idea how i can do that the best practice?
On of the possible approach is to use Subjects.
1) Store task list on the service and provide subscribable Subject
private tasks: Array<Task>;
public $tasks: BehaviorSubject<Array<Task>>;
constructor(private http: HttpClient) {
this.$tasks = new BehaviorSubject([]);
...
}
getAllTasks() {
this.http.get(environment.apiUri + 'tasks')
.subscribe(data => {
this.tasks = data;
this.$tasks.next(this.tasks);
});
}
updateTask(params) {
this.http.post(/* params */).subscribe((task) => {
this.tasks = this.tasks.map(t => t.id !== task.id ? t : task);
this.$tasks.next(this.tasks);
});
}
createTask(...) {
// again, do a request, update this.tasks and call $tasks.next
...
}
2) Make one service Subject subscription on the component instead of multiple service methods Observable listeners and update component's list automatically each time the service source has been changed
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) {
this.tasksProvider.$tasks.subscribe(tasks => this.tasks = tasks);
}
ngOnInit() {
this.tasksProvider.getAllTasks();
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked);
}
I'm getting this error and i'm new to angular 2 so i'm not 100% sure on how to resolve the issue, i'm connecting to a test API to return a javascript object which includes some dummy data. But my "this.onGet()" function is telling me that the supplied parameter does not match any signature of call target and i can't seem to figure out why.
(Essentially i'm just trying to populate the orderInfo array with the information from the API so i can use it across multiple page)
Any help appreciated :)
App.component.ts
import { Component, OnInit } from '#angular/core';
import { DetailsService } from './details.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [DetailsService]
})
export class AppComponent implements OnInit {
orderInfo = [
{
name: 'Test'
}
];
constructor(private detailsService: DetailsService) {
}
ngOnInit() {
this.onGet();
}
onGet(name: string) {
this.detailsService.getDetails()
.subscribe(
(orderData: any[]) => {
this.orderInfo.push({
name: name
});
console.log(orderData);
}
);
}
}
details.service.ts
import {Injectable} from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/Rx';
#Injectable()
export class DetailsService {
constructor(private http: Http) {}
getDetails() {
return this.http.get('http://swapi.co/api/people/1/?format=json', '')
.map(
(response: Response) => {
const orderData = response.json();
return orderData;
}
);
}
}
The signature of http get method is
get(url: string, options?: RequestOptionsArgs) : Observable<Response>
You are passing a extra string parameter
getDetails() {
///////////////removed below single quotes
return this.http.get('http://swapi.co/api/people/1/?format=json')
.map(
(response: Response) => {
const orderData = response.json();
return orderData;
}
);
Look into your
ngOnInit() {
this.onGet(); //////////nothing passed
}
where as your method signature is onGet(name:string) you are not passing anything as above
Your OnGet function is expecting a string parameter, which is not supplied while calling from ngOnInit.