ion-list display asynchronously added data to array - arrays

I am new in ionic. I trying to make an app which will search for Bluetooth devices and will display them.
I have created a service which search for Bluetooth devices. When a device found an event publishes like below:
this.event.publish("ibeacon", newBeacon);
Here is my event injection:
import { Events } from 'ionic-angular/util/events';
......
constructor(private event: Events){}
Here is how I subscribe to the event in order to get the published data:
this.event.subscribe("ibeacon", (newBeacon) => {
this.iBeacons.push(newBeacon);
});
As you can see I have declared an iBeacons Array where I push my received objects. The problem is when I try to display the iBeacons Array contents nothing displayed. Here is how I display my array:
<ion-content padding>
<ion-list>
<ion-item *ngFor="let beacon of iBeacons">
<ion-label>
{{ beacon.hash }}
</ion-label>
</ion-item>
</ion-list>
</ion-content>
The array at the beginning is empty.
I have have checked and I receive correctly my devices when I subscribe to the event.
I don't get errors.
I thing the data is not displayed because the data is added asynchronously in iBeacons array. Any idea?
Here are some of the iBeacons Array contains:
(4) [{…}, {…}, {…}, {…}]
0: {hash: "b5d787ac973341a59bf73838eededcb4", uuid: "fda50693-a4e2-4fb1-afcf-c6eb07647825", major: "10001", minor: "10301", lastFoundTime: 1518003454401}
1: {hash: "50aee081c9833e51ce00b9aa4a0c062d", uuid: "fda50693-a4e2-4fb1-afcf-c6eb07647825", major: "10001", minor: "10206", lastFoundTime: 1518003454391}
2: {hash: "1c8ecafb6efbbc37f905d95551291672", uuid: "fda50693-a4e2-4fb1-afcf-c6eb07647825", major: "10001", minor: "10208", lastFoundTime: 1518003454391}
3: {hash: "442e383d9c582985083b5b05f07161d2", uuid: "fda50693-a4e2-4fb1-afcf-c6eb07647825", major: "10001", minor: "10205", lastFoundTime: 1518003454392}
length: 4
__proto__: Array(0)
Here is the iBeacons array initialization:
iBeacons:any [] = [];

Try to use ChangeDetectorRef like this:
import { ChangeDetectorRef } from '#angular/core';
constructor(private cd: ChangeDetectorRef) {}
this.event.subscribe("ibeacon", (newBeacon) => {
this.iBeacons.push(newBeacon);
this.cd.detectChanges();
});

Related

can't query results of graphql query because am using 2 arrays within each other

Here is my map function, I am using react with gatsby.
when I run my graphiql browser, (an IDE graphql playground) I get group as an array, and edges is also an array.
the query is a static query and the mapping function is inside of a class based react component
{group.map(({ edges }) => {
console.log(group);
edges.map(index => {
return <p>Hello</p>
});
})}
However, the p tags are not displaying anything, but if I console.log("hello") it consoles hello 4 times, anyone got any ideas?
I am a little stumped.
the console.log returns
(3) [{…}, {…}, {…}]
0:
edges: Array(2)
0:
node: {tune: "awesome", title: "Awesome Song", playtime: "2:50", page: "249", filesize: "1.8", …}
__proto__: Object
1:
node: {tune: "awesome", title: "AwesomeSong 2", playtime: "4:05", page: "525", filesize: "2.6", …}
__proto__: Object
length: 2
__proto__: Array(0)
__proto__: Object
1:
edges: Array(1)
0:
node: {tune: "decent", title: "Awesome Song3", playtime: "4:06", page: "719", filesize: "2.4", …}
__proto__: Object
length: 1
__proto__: Array(0)
__proto__: Object
2: {edges: Array(1)}
length: 3
__proto__: Array(0)
Have you tried something like this?
{group.map(({ edges }) => {
return edges.map(({node})=> {
return <p>{node.title}</p>
});
})}
You need to return something in your first map() loop.
In addition, are you displaying the loop in a render() function? If not, you can't display a <p> tag.

Why do I get TypeError: _this.data.forEach is not a function

I am trying to retrieve data from the backend. These are the relevant parts of my code:
API call
getData(PrimaryId:number):Observable<DataDto[]>{
return this.httpClient.get(`${this.prefix}/<xyz>/${PrimaryId}/xyz`) as Observable<DataDto[]>
}
Component TypeScript
onRetrieveClicked() {
this.xyzService.getData(this.PrimaryId).subscribe(
(xyz: DataDto[]) => {
this.xyz = xyz
console.log(this.xyz)
console.log(this.xyz.forEach((data)=>data.name)
})
}
First console.log output
{content: Array(1), pageable: {…}, totalPages: 1, totalElements: 1, last: true, …}
content: Array(1)
0: {name: max, name: null, asset: null, …}
length: 1
..........
But when I try to print only the name in the second console, it says that forEach is not a function. How can I solve this
edit
Dto model
export interface DataDto {
name: string
asset: abcDto
status: StatusDto
tasks: efgDto[]
nextDate: string
}
The xyz variable that you type as DataDto[], an array, is actually an object. This can be seen in your console.log, an array would be enclosed in [], not {}
is an object --> {
content: Array(1), pageable: {…}, totalPages: 1, totalElements: 1, last: true, …}
content: Array(1)
0: {name: max, name: null, asset: null, …}
length: 1
}
The data you are looking for is most likely the response object's content so add an import for import {map} from 'rxjs/operators'; and transform the data you've gotten from the response:
this.xyzService.getData(this.PrimaryId).pipe(
map((xyzResponse: any) => xyzResponse.content)
).subscribe(
(xyz: DataDto[]) => {
this.xyz = xyz;
console.log(this.xyz);
let dataNames = xyz.map(data => data.name);
console.log(dataNames);
}
I've typed xyzResponse as any but you could ofcourse create a reusable type for it if the API always returns the object with content, pageable, totalPages, ...
Rxjs is the library that Angular uses to handle asynchronous programming, such as HTTP calls or component events. Rxjs chains asynchronous manipulations together in a pipe (hence the .pipe call). Inside of this pipe rxjs expects a chain of operators that will perform operations on the asynchronous data, one by one. The map operator takes the input value and returns a new value so that the value you subscribe to has been transformed from the HTTP response to the .content field of the HTTP response.
Working in this way fixes all TypeScript compiler errors and allows you to chain additional calls later, like retrying if the API times out, or catching errors, or merging in other HTTP calls.
It seems that your this.xyz is not an array, but has an array property called content, you should modify your response object in order to accept it.
You can check if your objects are arrays with the following method
Array.isArray(obj)
Update your code to this.
this.xyzService.getData(this.PrimaryId).subscribe(
(xyz: NewObject) => {
this.xyz = xyz
console.log(this.xyz)
//If you have doubts of what is comming is nice to check if your property is an array
if(Array.isArray(this.xhy.content) {
console.log(this.xyz.content.forEach((data)=>data.name) });
}
}
Create a new object in order to support your response
class NewObject {
content: Array<DataDto>
// other values here
}
Another approach is like #Robin says in the comment
this.xyzService.getData(this.PrimaryId).subscribe((xyz: {content: DataDto[]}) =>
{
this.xyz = xyz
console.log(this.xyz)
//If you have doubts of what is comming is nice to check if your property is an array
if(Array.isArray(this.xhy.content) {
console.log(this.xyz.content.forEach((data)=>data.name) });
}
}
It's because you are trying to loop through an object instead of array
I think you can try this:
console.log(this.xyz.content.forEach((data)=>data.name) })

use react render a nested object in jsx

I am trying to render a nested object from a firestore database in react jsx with the map function. The 'text' property like 'I will save document" is contained within what appears to be an object(document) that contains an array[blocks] that contains another array[inlineStyleRanges] that contains an object (text). I am trying to render the text object and I am having a hard time figuring out the syntax to make it render correctly.
The object has this structure:
(4) [{…}, {…}, {…}, {…}]
0:
description: "Lorem ipsum dolor sit amet, suspendisse velit"
document:
blocks: Array(1)
0:
data: {}
depth: 0
entityRanges: []
inlineStyleRanges: []
key: "8u7m4"
text: "I will save this document."
type: "unstyled"
__proto__: Object
length: 1
__proto__: Array(0)
entityMap: {}
__proto__: Object
id: Timestamp {seconds: 1551856294, nanoseconds: 879000000}
title: "TCC/NIBF SUMMARY SHEET"
__proto__: Object
my attempted render method looks like this:
render() {
const urlID = this.state.urlID;
const results = this.state.documents;
const postList = results.map((result, index) => {
if (urlID === result.id.seconds.toString()) {
return (
<Card key={result.id.seconds}>
<CardBody>
<CardTitle>File Name: {result.title}</CardTitle>
<CardText>File Description: {result.description}</CardText>
{/*<CardText>File Document Text: {result.document... }</CardText>*/}
</CardBody>
</Card>
);
} else {
return null;
}
});
return <div>{postList}</div>;
}
I used the new es6 Map function to make a new object map that I turned into an array using the spread operator and then looked at the structure of the object as an array in chrome dev tools.
After studying it, I found the correct syntax:
<CardText>File text: {result.document.blocks["0"].text}</CardText>

Dynamically render ACF fields from wordpress rest api in react

I'm trying to dynamically map out the response that i get from the wordpress rest api. The problem I'm having is that the response im getting looks like this:
(2) [{…}, {…}]
0
:
{id: 18, date: "2018-05-02T14:31:37", date_gmt: "2018-05-02T14:31:37", guid: {…}, modified: "2018-05-02T14:51:14", …}
1
:
{id: 17, date: "2018-05-02T14:31:18", date_gmt: "2018-05-02T14:31:18", guid: {…}, modified: "2018-05-02T14:51:23", …}
length
:
2
__proto__
:
Array(0)
Both these objects have another object inside them called acf that includes my fields that i want to render out.
This is how i want to render the fields:
const dateData = [
{
date: '18-04-23',
time: '9pm',
title: 'MGM Grand Garden Arena',
},
{
date: '18-04-23',
time: '9pm',
title: 'MGM Grand Garden Arena',
},
{
date: '18-04-23',
time: '9pm',
title: 'MGM Grand Garden Arena',
},
]
const dateRender = dateData.map((t, i) => (
<div key={i} className="date-item">
<p>{t.date}</p>
<p>{t.time}</p>
<p>{t.title}</p>
</div>
));
But it's not working because the acf fields is nested inside two different objects. The purpose of this is that the user should be able to add new dates in wordpress dashboard and it should render it out dynamically. Any tips?
Thanks!

cant print an object list in html

Object {0: Object, 1: Object, 2: Object, 3: Object, 4: Object, httpStatus: 200, httpStatusText: null, httpBodyText: "[object Object],[object Object],[object Object],[object Object],[object Object]"}
0:Object (example of object i opened to show content)
CountryInitials : "US"
Id: "101"
CountryName: "United States"
Population: 318.9
__proto__:
Object
1:Object
2:Object
3:Object
4:Object
this is an example from my browser that shows how im receiving the data, so its a object that contains objects, and I want to treat it in the html like its an array, and i thought it is but its not working....
this is the html:
<div *ngFor="#obj of myList>
<div><b>Country ID:</b> {{obj.Id}} <b>Country Name:</b> {{obj. CountryName}}}</div>
</div>
and its not working...I dont know why, i just want to present a list of the objects with country id and country name..
the EXCEPTION:
EXCEPTION: Error trying to diff '[object Object]' in [myList in EntityBulkCmp#32:31]
could someone please help me figure this out?
thanks!
You can use the pipe json to print an object inside the template: https://angular.io/docs/ts/latest/api/common/index/JsonPipe-pipe.html
#Component({
selector: 'json-pipe',
template: `<div>
<p>Without JSON pipe:</p>
<pre>{{object}}</pre>
<p>With JSON pipe:</p>
<pre>{{object | json}}</pre>
</div>`
})
export class JsonPipeComponent {
object: Object = {foo: 'bar', baz: 'qux', nested: {xyz: 3, numbers: [1, 2, 3, 4, 5]}};
}
The Exception says items in myList are not unique. Probably you have some repeated elements.
Angular needs to keep track of which item it is enumerating.
Use trackBy option, find the syntax below
<li *ngFor="let item of items; let i = index; trackBy: trackByFn">...</li>
refer https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html for complete usage of the directive.
you can use key and value to print the json format...
In which key is 0, 1, etc (as in your case) and value is object (as in your case)...

Resources