How to loop through an object and push into an array - arrays

What I'm working with
angular2
firebase
What I have
A returned object
Each item in the object has a URL property
What I would like to do
Loop through each of the items in the object and get the URL property
Pass that into a firebase storage variable
Push the URL property into an array to make available for my HTML
note: I have this working by hard coding a url, I just need some assistance looping through the object to get the other urls in the object.
Component.ts
'this.imagesToDisplay' will return an object of object (image below)
this.activatedRoute.data
.subscribe((
data: { issueData: any, issueImageData: any }) => {
this.issueToDisplay = data.issueData;
this.imagesToDisplay = data.issueImageData;
this.testing(this.imageToDisplayArray);
});
Comnponent TS - Testing method
So this is hardcoded and pushes the hardcoded url into the array and displays correctly through databinding with the HTML. Cool. However, I would like to loop through the 'imagesToDisplay' object and get both returned urls.
testing(imageToDisplayArray) {
// this works with one url
var storage = firebase.storage().ref().child("image/-Kosd82P-bmh4SFetuf3/-Kosd8HhGmFiUhYMrlvw/30DD9F39-4684-4AA0-9DBF-3B0F0C3450A4.jpg");
storage.getDownloadURL().then(function(url) {
imageToDisplayArray.push(url);
console.log(imageToDisplayArray);
});
}
Any help here would be massively appreciated.
Note: I think this question here is what I'm trying to do, I'm just not sure how to integrate that into my current code. Any help would be awesome.
Stack Overflow question on firebase storage looping
UPDATE
So, I'm incredibly close now. I just have one issue. The code below loops through the returned data and extract the URL properties. I use the url properties to connect to the firebase storage and return the download URLs. Both of these are logged to the console! Awesome. I now have the URLs i needed! The issue I'm having is, it will only let me push these values to a local array. In this instance 'var array'. I need to push to an array that's outside of the 'activatedRoute' 'method'. Anytime I do, it returns as undefined.
this.activatedRoute.data
.subscribe((
data: { issueData: any, issueImageData: any }) => {
this.issueToDisplay = data.issueData;
this.imagesToDisplay = data.issueImageData;
var array = [];
data.issueImageData.forEach(image => {
// Reference to the image URL
var image = image.url;
// Firebase storage
var storage = firebase.storage();
// Path reference
var imagePathReference = storage.ref().child(image);
// Get Download URL
imagePathReference.getDownloadURL().then(function (url) {
console.log(url);
array.push(url);
})
});
});

I would recommend you to use the features rxjs provides you:
this.activatedRoute.data.switchMap(data => {
let parsedData = {
issueToDisplay: data.issueData,
imagesToDisplay: data.issueImageData
}
let imageUrls$ = data.issueImageData.map(image => {
var imagePathReference = storage.ref().child(image);
return Observable.fromPromise(imagePathReference.getDownloadURL())
});
return Observable.forkJoin(imageUrls$).map((...urls) => {
return Object.assign(parsedData, { urls });
})
}).subscribe(data => {
/*
data looks like this:
{
issueToDisplay: any,
imagesToDisplay: any,
urls: string[]
}
*/
});

If I'm correct, you're looking for a solution to map an array-like object of objects to an actual array of objects.
Here is a way to do just that:
var object = {
'0': {
"url": "url1",
"name": "obj1",
"data": 1234
},
'1': {
"url": "url2",
"name": "obj2",
"data": 5678
},
'length': 2
}
var sliced = Array.prototype.slice.call( object, 0 );
console.log(sliced)
Couple remarks:
If you wonder how this works, check this post.
Alternative syntax that you could encounter looks like [].slice.call()
If you want to perform array-like operations, you can probably do that right away with Array.prototype.<METHOD>.call(object, <CALLBACK>
For example:
Array.prototype.map.call(object, function(el) { // return your enhanced element })

So, this works. Not entirely sure how clean it is. But it works.
this.activatedRoute.data
.subscribe((
data: { issueData: any, issueImageData: any }) => {
this.issueToDisplay = data.issueData;
this.imagesToDisplay = data.issueImageData;
var localImageArray = [];
data.issueImageData.forEach(image => {
// Reference to the image URL
var image = image.url;
// Firebase storage
var storage = firebase.storage();
// Path reference
var imagePathReference = storage.ref().child(image);
// Get Download URL
imagePathReference.getDownloadURL().then(function (url) {
localImageArray.push(url);
})
this.getIssueImageArray(localImageArray);
});
});
}
// Get Image Array
getIssueImageArray(array) {
this.imageToDisplayArray = array;
}

Related

Add query parameter in the middle of the URL using react fetch

I am writing a service for all my RestApis where I store RestApis and then use it when I need by calling methods.
RestApiService.js
let getData = 'https://myURL?id=123456';
export const getIndividualUsers = (resourceId) => {
const queryParams = {
userId: resourceId
};
queryParams.authorization = sessionStorage.getItem("authorization");
}
Object.keys(queryParams).forEach((k) => {
queryParams[k] = (typeof (queryParams[k]) !== 'string') ? JSON.stringify(queryParams[k]) : queryParams[k];
});
return getData.get('', queryParams);
};
I call this method when I need data using the method name and use the response in my code:
getIndividualUsers(123456).then((response));
Now one of my API has variable in the middle of the URL such as
URL: 'https://myURL/${variable}/children/12'
How do I pass queryParams(variable) in the middle of the Url? I will have variable value when I call the method that fetches the URL and not while defining the the URL.
Which library are you using? Anyway you can do like below always.
const getChild = (parentName, id) => {
let url = `https://myURL/${parentName}/children/${id}`;
...
};

Get ID element from url and store it in a session array every time page loads

In reactjs, I am trying to store the id to session storage array which comes from URL, for example, http://localhost:3000/#/carnivallist/171 what's the solution to store all the ids?
I can only store one id. when the page refreshes the id is getting replaced on the session storage.
componentDidMount() {
if(this.props.params.id) {
let pro_id=[this.props.params.id];
console.log(pro_id);
console.log("otem");
let items=sessionStorage.getItem("carnival_dones");
console.log(items);
if(items!=""){
this.setState({ carnival_done: [...this.state.carnival_done,{carnival_done:pro_id}]});
}else{
this.setState({carnival_done:pro_id});
}
}
}
I expect to get all ids in an array but the session storage stores only the last value get saved. and the value not accessible through the session get method
You would have to save an array, something like below code:
let items = JSON.parse(sessionStorage.getItem("carnival_dones"));
if(!items){
items = []
}
items.push(this.state.carnival_done)
sessionStorage.setItem("carnival_dones",items);
Try saving array as json and parse it when retrieving.
componentDidMount()
{
if(this.props.params.id)
{
let pro_id = this.props.params.id;
let items = JSON.parse(sessionStorage.getItem("carnival_dones"));
if(items)
{
this.setState({ carnival_done: [...this.state.carnival_done, pro_id]});
}
else
{
this.setState({carnival_done: [pro_id]});
}
}
}
// Save session
save = () =>
{
sessionStorage.setItem("carnival_dones", JSON.parse(this.state.carnival_done));
}
The problem was I was using the
componentDidMount method instead of using componentWillMount so I found a solution changing the hook
componentWillMount() {
if(this.props.params.id) {
let pro_id=[this.props.params.id];
console.log(pro_id);
console.log("otem");
let items=sessionStorage.getItem("carnival_dones");
console.log(items);
if(items!=null){
this.setState({carnival_done:[...this.state.carnival_done,[items,pro_id]]});
//this.setState({ carnival_done: [...this.state.carnival_done,pro_id]});
console.log(this.state.carnival_done);
}else{
this.setState({carnival_done:[pro_id]});
}
}
}
Thank you so much for your support

Applying proxy object instead of array in MobX-React store

I'm here trying to refactor a working app I made which get events from a Database (in order to be later displayed on a scheduler).
So here I am using an #observable events variable in which I'm setting an array I get using a POST request to my database.
But when I'm later trying to show in console what is now in my variable, instead of the array of strings I should have, I now have a Proxy object...
Can someone help me to understand what should I do in order to get back my array instead of the Proxy object ?
Thanks in advance !
PS : here's a bunch of the code
#observable events = [];
loadAgendaData = (event) => {
let viewModel = new SchedulerData('2017-12-18', ViewTypes.Week, false, false, {});
axios.post('http://localhost:5002/api/getCreneaux', {
id_grpe: event.value
}).then((res) => {
res.data.forEach((element) => {
element.start = moment.unix(element.start).format("YYYY-MM-DD HH:mm:ss");
element.end = moment.unix(element.end).format("YYYY-MM-DD HH:mm:ss");
})
viewModel.setEvents(res.data)
console.log(res.data); // this shows the Array
this.events = res.data; // giving this.events the value of the array
})
}
anotherFunction = (event) => {
console.log(events); // this unfortunately shows a Proxy object
}

Sending json object as json array to an API

I have an API that accepts data format as [ { "record_id": "TestID3" } ]. I am trying to send record_id field using the form below in my angular project:
html:
<input id="record_id" type="text" class="form-control" [(ngModel)]="member.record_id" name="record_id" #record_id="ngModel" placeholder="Enter Record ID">
component.ts:
export class MembersAddComponent implements OnInit {
member: Array<Object> = [];
constructor(private service: DataService ) { }
ngOnInit() {
}
submit() {
this.service.importRecord(this.member).subscribe(member => {
this.member = member;
}, error => {
console.log(error);
});
}
}
And my service.ts:
importRecord(data): Observable<any> {
const formData = new FormData();
formData.append('token', this.token);
formData.append('content', this.content);
formData.append('format', this.format);
formData.append('returnFormat', this.returnFormat);
formData.append('type', this.type);
formData.append('overwriteBehavior', this.overwriteBehavior);
formData.append('forceAutoNumber', this.forceAutoNumber);
formData.append('data', data);
formData.append('returnContent', this.returnContent);
return this.http.post(this.baseUrl, formData).map(res => res.json())
.catch(this.handleError);
}
The error that I get is below:
{"error":"The data being imported is not formatted correctly. The JSON must be in an array, as in [{ ... }]."}
I also tried member:any = {}, member:Object = {}; but I got the same error. I am thinking that I am unable to format my member object as requested format. But I couldn't make it as desired format.
[ { "record_id": "TestID3" } ]
That is an array, containing a single element, which is an object.
member: Array<Object> = [];
that defines an array with no element at all.
[(ngModel)]="member.record_id"
That will try to read and write the property record_id of member, which is an array. It will not magically add an element to the array and set its property.
So what you need is an object that will be populated by the form. And then you need to put that object into an array before to send the array to the API.
Start by defining an interface to describe your object:
interface Member {
record_id: string;
}
Then use one as the model for your form:
member: Member = {
record_id: '';
};
...
[(ngModel)]="member.record_id"
Then put that member into an array before sending it:
submit() {
const data: Array<Member> = [this.member];
this.service.importRecord(data)...
It's difficult to tell if this is due to an incorrectly formatted response from the POST or the body of the POST.
Things you can do:
Check the network tab in Chrome to verify that the request is being sent, it's content is valid JSON (use an online validator)
Check your API backend to see if the data you're sending is being saved, if so the error is with the format of the JSON in your response.
Verify in Chrome that the response data in the network request is valid JSON.
If all of these are true, you may need to consider using headers such as {requestType: 'json'} as detailed in the Angular docs here: Request/Response Headers
If these are not true, then you will need to change the model of the object you are sending to reflect the object which is expected.

How to call the $firebaseArray in the cloud function of firebase

So in my angular JS web app, I have a function that calls on a node in the firebase database called orderedPlayers and returns it as an array as follows:
$firebaseArray(orderedPlayers)
.$loaded(function(loadedPlayers) {
// function in here
});
When attempting to do something similar in the cloud function I am experiencing problems. Is there a way to return the the players node as an array?
I know i can access the database as follows:
admin.database().ref('orderedPlayers');
but the $firebaseArray doesnt work.
These docs can help: https://firebase.google.com/docs/database/admin/retrieve-data
snapshot.val() will return an object that can be referenced as a key-value array. In your case:
admin.database().ref('orderedPlayers').on("value", function(snapshot) {
var loadedPlayers = snapshot.val();
//access your players here
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
To the best of my knowledge cloudfunctions does not include firebaseArray. You can instead just make the players children into an array.
so:
let yourArray = [];
admin.database().ref('orderedPlayers').once('value').then(snap => {
snap.forEach(childSnap => {
yourArray.push(childSnap));
});
});
or you can use the children:
let yourArray = [];
admin.database().ref('orderedPlayers').on('child_added',snap => {
yourArray.push(snap);
});
*on('child_added') will always be called at least once so it removes the need to loop over the children.
If you want to query the database by a specific value you just add something like orderByChild('order') after the ref and before calling once or on

Resources