sorry for the noob question.
I created an http request and retrieved some pokemon data and put it in an object called pokemon, like so:
export class AppComponent implements OnInit{
title = 'Pokedex';
apiURL = 'https://pokeapi.co/api/v2/pokemon/1';
pokemon = {};
constructor(private http: HttpClient){}
ngOnInit(): void{
this.http.get(this.apiURL).subscribe(data =>{
const pokemon = {
name: data['name'],
id: data['id'],
abilities: data['abilities'].map( ability => ability['ability']['name']),
types: data['types'].map( type => type['type']['name']),
image: data['sprites']['front_default']
}
console.log(pokemon);
When I console log the object, it outputs in the console fine.
However, when I try to display it in an html {{ pokemon }} it just returns [object, Object]
How can I get around this?
I have tried the methods suggested below.
{{pokemon.name}}, {{pokemon[name]}} and {{pokemon?.name} display a blank page.
{{ pokemon | json }} returns an empty object, in the form of {}.
Am I perhaps doing something else wrong?
You need to use the json pipe
<pre>{{ pokemon | json }}</pre>
OR
<div> Id: {{ pokemon.id }} </div>
<div> Name: {{ pokemon.name }} </div>
<div> Abilities:
<ul>
<li *ngFor="let ability of pokemon.abilities"> {{ ability }}</li>
</ul>
</div>
<div> Types:
<ul>
<li *ngFor="let type of pokemon.types"> {{ types }}</li>
</ul>
</div>
call property as {{pokemon?.name}}
You can't use object directly. You have to access object properties by either . (Dot) notation or object[property] way.
In your case, if you want to use the property of name then use
{{ pokeman.name }}
or
{{ pokeman[name] }}
Related
I am trying to display the currency name or key like "USD", "AUD", "EUR" with their respective "last" and "buy" properties from this HTTP response:
and I just get back a list of "key" strings like this
but I can't figure out why my "key" is being returned as a string here.
It's making it difficult for me to programmatically access the properties for each currency
this is my dashboard.component.ts
prices;
bitcoinOwned;
ngOnInit(): void {
this.data.getPrice()
.pipe(map(result => {this.prices = result, console.log("result", result)
for (let key in result) {console.log( key)}
} ))
.subscribe();
}
my data.service
getPrice() {
var url = "https://blockchain.info/ticker";
return this.http.get(url);
}
and my template
<div>
{{ prices |json }}
</div>
<div>
USD last: {{ prices?.USD.last |json }} USD sell: {{ prices?.USD.sell |json }}
</div>
I can access the properties when I do it manually for each key like this but I need to iterate over the keys and do it more programmatically so any help would be appreciated!!
You may want to use Angular's KeyValuePipe.
Then, you can do something like this:
<div *ngFor="let item of prices | keyvalue">
{{item.key}} last: {{ item.value.last |json }} {{item.key}} sell: {{ item.value.sell |json }}
</div>
I think you can use Object.keys() on the object to return the key value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Im trying to iterate over an array but page is displaying [ object Object] instead. How can I get data.id of my example?
Service:
return this._http.get<CustomersList[]>(this.apiUrl,{ headers: reqHeader });
My json looks like this:
[ {"current_page":1,"data":[{"id":25},{"id":26}] }]
And here is my component:
customerslist$: CustomersList[];
return this.customerdataService.getCustomersList().subscribe(data => this.customerslist$ = data);
Would be great if anybody can help me?
The data property is an array contained in an array. You either need two *ngFor directives
<ng-container *ngFor="let customer of customerslist$">
<ng-container *ngFor="let item of customer.data">
{{ item.id }}
</ng-container>
/ng-container>
Or if you're sure the customerslist$ array will always contain only one element, you could access the first element directly.
<ng-container *ngFor="let item of customerslist$[0].data">
{{ item.id }}
</ng-container>
Also if you're aren't using the this.customerList$ in the controller, you could skip the subscription in the controller and use the async pipe in the template. It takes care of any potential memory leak issues due to open subscriptions.
Contoller
customerslist$: Observable<CustomersList[]>; // <-- typeof `Observable`
ngOnInit() {
this.customerslist$ = this.customerdataService.getCustomersList(); // <-- don't subscribe yet
}
<ng-container *ngIf="(customerslist$ | async) as customerslist">
<ng-container *ngFor="let customer of customerslist">
<ng-container *ngFor="let item of customer.data">
{{ item.id }}
</ng-container>
</ng-container>
</ng-container>
By convention, variable names suffixed with a dollar sign (customerlist$) are used to denote observables.
If you are using Observable $ sign at the end of variable denotes observable,
in that case you do not need to subscribe only return value, in template you can subscribe using async pipe which automatically unsubscribe as well to prevent memory leak and a recommended approach.
Here we assume we are only taking first element of array that why directly accessing it giving first index, otherwise we need to iterate that array in template as well.
customerslist$: Observable<CustomersList[]>;
this.customerslist$ = this.customerdataService.getCustomersList()
.pipe(map(res) => res[0].data));
In template use async pipe to subscribe
<ng-container *ngFor="let data of customerslist$ | async">
<span> {{ data.id }} </span>
</ng-container>
WITHOUT OBSERVABLE
customerslist: CustomersList[];
this.customerdataService.getCustomersList()
.subscribe((res) => this.customerslist = res[0].data));
In template
<ng-container *ngFor="let data of customerslist">
<span> {{ data.id }} </span>
</ng-container>
I have this object:
this.item = {
name:"Michael",
age:18
};
I want to put on HTML
name: Michael
age: 18
<div >{{ item (name) }}</div> --??? should put name
<div>{{ item.name }}</div>
<div ">{{item (age)}}</div> --?? should put age
<div>{{ item.age}}</div>
How can I get the string name and age from the object?
Use keyValue pipe
<div *ngFor="let item of item | keyvalue">
{{item.key}}:{{item.value}}
</div>
stackblitz
You should avoid calling a function (which some suggest in comments) inside template. If you do that, that function will be called every time change detection runs. Which is bad. Almost always prefer pipes over method call inside the template.
You can try something like:
<div *ngFor="let key of item">
<div>{{key}}: {{item[key]}}</div>
</div>
I can't access the properties of my Firestore document during string Interpolation. The regular JSON output works fine though. Here's the code:
Working
<h3>{{ teacher | async | json }}</h3>
Output:
Not working
<h3>{{ teacher.name | async | json }}</h3>
and
<h3>{{ teacher.name | async }}</h3>
Output:
Typescript code
interface Teacher {
name: string;
}
teacherDoc: AngularFirestoreDocument<Teacher>;
teacher: Observable<Teacher>;
var placeToSearch = 'Teachers/'+this.selectedTeacher;
this.teacherDoc = this.afs.doc(placeToSearch);
this.teacher = this.teacherDoc.valueChanges();
You're just slightly off with the async pipe. The object needs to be unwrapped first, then you call it's properties. It should look like:
{{ (teacher | async)?.name }}
Or better yet, set a template variable to avoid using the async pipe over and over:
<div *ngIf="teacher | async as t">
{{ t.name }}
{{ t.field }}
{{ t.whatever }}
</div>
Your interface should have both name and field
interface Teacher {
name: string;
field: string;
}
<h3>{{ teacher?.name | async }}</h3>
I have been trying to display a json file having multiple arrays in it on the front-end div tag in using Services Angular2 using Typescript. Can anyone help?
Also, If anyone can help transforming this code by adding Model and Interface class would be very helpful.
Here is the code:
SERVICE
export class HttpServiceDemo{
_data: any;
private url: string = "assets/sample.json"
constructor(private http: Http){}
getMyOrder(){
//return this.http.get(this.url)
// .map((response: Response)=> response.json());
return this.http.get(this.url)
.map(res => this.http = res.json().myOrder);
}
}
component.ts
export class SimpleHTTPComponentComponent implements OnInit {
data:any;
Order_date:any;
OrderNumber: number;
P_O_Number:number;
Total: number;
Quote_Status: string;
Expiration_Date: any;
Quote_Created_On: any;
constructor(public vara: HttpServiceDemo) {
}
ngOnInit() {
//calling myorder from json
this.vara.getMyOrder().subscribe(response => {
this.data=response;
for (var myOrder in this.data)
{
console.log(myOrder, this.data[myOrder]);
this.Order_date=this.data[myOrder].Order_Date;
this.OrderNumber=this.data[myOrder].OrderNumber;
this.P_O_Number=this.data[myOrder].P_O_Number;
this.Total=this.data[myOrder].Total;
this.Quote_Status=this.data[myOrder].Quote_Status;
}
})
}
sample.json
---------------
{
"accOrder":[
{
"Order_Date": "10-sep-1981",
"OrderNumber" : "E12345",
"P_O_Number": "P12345",
"Total": "123",
"Quote_Status": "In Progress"
},
{
"Order_Date": "1-oct-1981",
"OrderNumber" : "E82398",
"P_O_Number": "P87815",
"Total": "265",
"Quote_Status": "In Progress"
},
{
"Order_Date": "21-nov-1981",
"OrderNumber" : "E52367",
"P_O_Number": "P76549",
"Total": "454",
"Quote_Status": "In Progress"
},
{
"Order_Date": "10-dec-1981",
"OrderNumber" : "E42840",
"P_O_Number": "P23632",
"total": "123",
"Quote_Status": "Completed"
}
]
}
You are saying your console.log() shows the JSON just fine ?
Then, your data is correctly fetched into your component's data attribute.
You just have to go through your attribute in your template using *ngFor directive then.
Plunkr : https://plnkr.co/edit/4IdV3OHyNFNi90KXQQHP?p=preview
template: `
<div>
<div *ngFor="let order of data.accOrder" style="border: 1px solid lightgrey; padding: 15px; margin: 5px 0;">
Order_Date : {{ order.Order_Date }} <br>
OrderNumber : {{ order.OrderNumber }} <br>
P_O_Number : {{ order.P_O_Number }} <br>
Total : {{ order.Total }} <br>
Quote_Status : {{ order.Quote_Status }} <br>
</div>
</div>
`
PS : No need for your "for" loop inside ngOnInit() , this is not how you should access the data.
You should check out the ngFor doc to learn more about it.
EDIT :
As I said in my comment below, my previous Plunker was using raw data while you use asynchronous data in your use case (it's coming from an Observable sent from your service).
To make it work then, you have to check if your component already received the data before you try to display it. For that, you need to use the *ngIf directive.
New Plunkr : https://plnkr.co/edit/W5qykrh4blplGxTyp8aC?p=preview
template: `
<div *ngIf="data; else loading">
<div *ngFor="let order of data.accOrder" style="border: 1px solid lightgrey; padding: 15px; margin: 5px 0;">
Order_Date : {{ order.Order_Date }} <br>
OrderNumber : {{ order.OrderNumber }} <br>
P_O_Number : {{ order.P_O_Number }} <br>
Total : {{ order.Total }} <br>
Quote_Status : {{ order.Quote_Status }} <br>
</div>
</div>
<ng-template #loading>Fetching the data from the webservice... Wait 3 seconds !</ng-template>
`,
You have to create a parent div to the one with your *ngFor directive. In this parent div, use the *ngIf="data" directive. Everything inside it will not be displayed until there is some data into the data attribute.
I used here an if/else syntax which appeared with Angular4. But you don't need that. That's just here to display a message while there is no data. It could be a loading spinner for example, to let the user know he has to wait.
If you don't want to use this if/else condition, you can do it without it like that :
template: `
<div *ngIf="data">
<div *ngFor="let order of data.accOrder" style="border: 1px solid lightgrey; padding: 15px; margin: 5px 0;">
Order_Date : {{ order.Order_Date }} <br>
OrderNumber : {{ order.OrderNumber }} <br>
P_O_Number : {{ order.P_O_Number }} <br>
Total : {{ order.Total }} <br>
Quote_Status : {{ order.Quote_Status }} <br>
</div>
</div>
`,
Hope this helped :)