Nested *ngFor in Observable Array - html

I am trying to bind a nested observable array using Angular 6 in my HTML and show the list(image_urls) in my carousel.
However, I am unable to bind the nested array. Any help or advice is much appreciated. Thanks in advance
This is what I have so far:
Components.ts
getAvailableCars()
{
this.cars$ = this.carService.getAvailableCars();
this.cars$.subscribe(car => {
car.forEach(c => {
c.image_urls = new Array<any>();
this.fileUploads = this.uploadFileService.getFiles(c.car_id);
this.fileUploads.subscribe(res => {
c.image_urls = res;
});
});
});
}
HTML
<div class="row" *ngFor="let car of cars$ | async”>
<span>{{car.name}}</span>
<mdb-carousel [isControls]="true" [animation]="'slide'”>
<mdb-slide *ngFor="let file of car.image_urls | async”>
<span>{{file.url}}</span>
</mdb-slide>
</mdb-carousel>
</div>
Console
Car(3) [{…}, {…}, {…}]
0:
car_id: 30
exterior_color: 4
fuel_type_name: "Petrol"
image_urls: Array(2)
0: FileUpload {url: "https://s3.amazonaws.com/xx/30/SocialPost_5695408_facebook.png"}
1: FileUpload {url: "https://s3.amazonaws.com/xx/30/logo_size.jpg"}
length: 2
__proto__: Array(0)
If i use this.fileUploads directly in the Carousel it works, but not when i push it to c.image_urls. Since, I have multiple cars and each have different image urls, I need to add the image_urls to the object of car.
Thanks again!

I got it working. I was modifying the observable in subscribe instead of in map.

Related

Angular Get method returns an Undefined instead of object

I am an Angular beginner and I've made a service and made all the set up so that the Get method works on a JSON file and it worked! but the problem is whenever I want to access to the data inside the JSON file it tells me that it is undefined, and I want to use it as an object in the ts file.
It works when using data biding like this {{stats | JSON}}, but I couldn't use it in the TS. can I convert this 'undefined' to a simple object?
stats: any;
constructor(private statsData: StatDataService) {
this.statsData.GetEmbedded().subscribe((data: any) => {
this.stats = data;
});
}
`
for example I can't use stats.preOrders[0]
To better understand the situation, let's create an example.
example.component.ts
interface Statistics {
median: number;
average: number;
}
export class Example {
// stats is undefined until GetEmbedded() fires
stats?: Statistics;
constructor(private statsData: StatDataService) {
this.statsData.GetEmbedded().subscribe((stats: Statistics) => {
this.stats = stats;
});
}
}
example.component.html
<div>The median is: {{ stats.median }}</div>
Why will this example result in an error? Your variable stats initially is undefined, so it will not have any properties. GetEmbedded() will take some milliseconds to fire but in the same time, the template already tries to access stats.median.
One option to solve this problem would be to check if the variable stats is not undefined and if it is not, access the properties you need.
example.component.html
<div *ngIf="stats">The median is: {{ stats.median }}</div>

Rendering data from HTTP POST Angular 8

I'm kinda new to Angular and I need to do a function that does an http.post on click and it works (POST DONE is returned and I get the data), the problem is that i need to render data inside tables but 'postReponse' returns only [Object Object] in my html file and I can't find a way to render the data as it should, does anyone have a fix for this issue please ?
Here's the code sample :
public postReponse: any;
postRefs(){
return this.httpClient.post('someUrl',
{
"someBody"
})
.subscribe(
data => {
console.log("POST DONE", data)
return this.postResponse = data;
},
error => {
console.log("ERROR POST", error)
}
)
}
//home.component.html
<tr>
<td>{{postResponse}}</td>
<td>{{postResponse}}</td>
<td>{{postResponse}}</td>
<td>{{postResponse}}</td>
</tr>
postResponse is an object with keys and values, for example if it contains two attributes id and name then it will look like this :
{ id : 1, name = 'name' }
So if you need to access to the name attribute you need to write inside your html:
<td>{{postResponse.name}}</td>

Observable with Angular 4 , NgFor only supports binding to Iterables such as arrays

Yes, I see that other people get this error , I just don't quite get how to fix it in my code
private _url = 'https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH,LTC,EOS,DASH&tsyms=USD'
If I didn't have the return it does not crash with the error , but I do want to return the data.
I have a component that calls up this method ( in this service ts file )
Subscriber:
getAllCoins() {
var blah = [];
return this.getCoins().subscribe(
data => {
blah = data;
//console.log('subscriber coins', blah)
}
)
}
Calls this code
getCoins() {
return this.http.get(this._url)
.map((response: Response) => response.json())
//.do(data => console.log(data))
.do(data => console.log('All: ' + JSON.stringify(data))) // do operator to peek
.catch(this.handleError);
}
Now, I see that the data from the url looks like this
{
"BTC": {
"USD": 3349.1
},
"ETH": {
"USD": 296.3
},
"LTC": {
"USD": 47.56
},
"EOS": {
"USD": 1.83
},
"DASH": {
"USD": 195.83
}
}
How can I prevent from getting this error errors.ts:42 ERROR Error: Uncaught (in promise): Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
UPDATE for comment question
#Component({
template: `
<div>test</div>
<div *ngFor="let coin of coinsList">
abc
</div>
`
})
As others have said, *ngFor only works on iterables.
There are a couple of methods that can be done to overcome this problem. Ones that come to my mind right now are:
1) You can push your list of objects to an Array.
this._ConfigurationService.getCoins()
.subscribe(
(data)=> {
for(let key in data){
this.coinsList.push(data[key]);
}
},
(error) => console.log("error : " + error)
);
template:
<div *ngFor="let coin of coinsList">
<span>{{coin | json}}</span>
</div>
Full plunker example: http://plnkr.co/edit/zrzVF8qKl8EvKKp2Qt45?p=preview
2) You can convert the response from object to an iterable using a pipe as shown in here: How to iterate [object object] using *ngFor in Angular 2
3) You can implement the iterable function to your object as shown here: Angular NgFor only supports binding to Iterables such as Arrays.
4) You can create special directive as shown here: Can ngForIn be used in angular 4?
My suggestion would be to use the first one for simplicity.
As the erorr says you are trying to do a ngFor over Object, it works over any iterables.
Probably you can iterate over them and create an array, and then use it for the ngFor.

Angular2 Is it possible to get deep nested json value without using ngFor?

I am currently getting json object from server and the object also has many nested json object as well. So far, I've been using *ngFor = "let a of data | pipe" (the pipe to get deeply nested value) and single interpolation {{a.value['someValue']}} to get the deep nested value of json object for other situations but this isn't serving my purpose right now since I don't want to loop my json.
Is there any way to get deeply nested json value without using ngFor?
The part of json object I am getting from server.
UserProfile:
{name: 'Jess'
University: 'UC Berkley'
Major: 'Media Communication'
birthday: 1994}
categoryInfo:
["inish work with quality"]
currentArea
:"CA"
introInfo {
experience: [
0: {Company: 'Atlas', workingYears: 1, **recLetter**:'She was on time always,
never late. The quality of her work is very high-level.'}
1: {Company: 'Footstep', workingYears: 2, recLetter:'She was on time always,
never late. The quality of her work is very high-level.'}
]
introduction: "Hello I'm Jess"
}
And if I use aforementioned method, it will just loop 4 keys (UserProfile, categoryInfo, currentArea, and introInfo) which I don't want.
How can I get value that's in bold (recLetter) without using *ngFor?
in my component, I am doing this.
userInfo: UserDetailInfo[];
getUserDetail(): void {
this.userDetail.getUserDetail()
.subscribe
(
userInfo => this.userInfo = userInfo,
error => this.errorMessage = error
)
}
And I tried this in the html template but didn't work and I didn't know how to get 'recLetter'
{{userInfo.experience['0']}}
Please help!
Thank you in advance
For the starters, lets assume you get experience array always the same, with 2 elements.
The only thing that you need to do in the html is this:
{{ userInfo.experience[0].recLetter }}
In case you want to loop through the whole array exeperience and display recLetter you can do this:
<div *ngFor="let item of userInfo.experience">
{{item.recLetter}}
</div>
Try this
properties.pipe.ts
import {Pipe} from '#angular/core';
#Pipe({name: 'properties'})
export class PropertiesPipe {
transform(o: {}) {
return Object.entries(o).map(([key, value]) => ({
key,
value
}));
}
}
app.module.ts
import {propertiesPipe} from './properties.pipe';
#NgModule({
declarations: [PropertiesPipe, /* whatever else was here */],
// ... whatever else was here
}) export class AppModule { }
component.html
<ul>
<li *ngFor="property of userInfo | properties">
<span *ngIf="!Array.isArray(property.value)">
{{property.key}}: {{property.value}}
</span>
<span *ngIf="Array.isArray(property.value)">
{{property.key}}: <span *ngFor="value of property.value">{{value}}, </span>
</span>
</li>
</ul>

Cannot read property 'name' of null Angular2 JSON

I got this code in AppComponent:
getPlanetsToView(page){
let pageToView = page*10 + 10;
for(var i=0; i<pageToView; i++){
this.planetsToView.push(this.planets.planets[i]);
}
}
ngOnInit() {
this.http.get('app/planets.json').subscribe(res => {
this.planets = res.json();
console.log(this.planets);
this.getPlanetsToView(0);
});
And I have this in template:
{{planetsToView[0].name | json}}
I have got problem:
Photo
When I tried with {{planetsToView[0] | json }} it works but contain another properties also.
Could be this problem:
At the time your component is initialized your JSON is not yet loaded into this.planets because the http.get call is asynchronous. Can you try this in your template: (Note the ? which is added)
{{planetsToView[0]?.name | json}}
The ? is called elivs operator and is used to safe guard against undefined references in view templates. Read more here: