Firebase values are properly pulled but cannot be accessed? - javascript

I'm running into a weird issue where once I push a value to a Firebase object, two things happen:
I can't access it in the array I receive when I pull the object from Firebase.
The array I receive has no length property.
Here is what my Firebase structure looks like:
"user_solutions": {
"0":
{
"user_id": 0,
"clue_id": 0,
"hunt_id": 0,
"completed": 1
},
"1":
{
"user_id": 0,
"clue_id": 1,
"hunt_id": 0,
"completed": 0
},
"2":
{
"user_id": 0,
"clue_id": 1,
"hunt_id": 1,
"completed": 0
}
},
"-KHxBMZwVMzyiMIcbMdr":
{
clue_id: 1,
completed: 0,
hunt_id: 0,
user_id: 0
}
Here is the problematic function:
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', (snap) => {
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[i].hunt_id == 0) {
solutionsForThisHunt.push(solution[i]);
}
}
this.populateArray(solutionsForThisHunt);
});
When I run the debugger, solution has the value Object {0: Object, 1: Object, 2: Object, -KHxBMZwVMzyiMIcbMdr: Object}, but the length property is undefined. solutionsForThisHunt never gets populated. Also, I can access the objects individually in the debugger via snap.val()[0]/snap.val()[1]/snap.val()[2], but for some reason when I try accessing snap.val()[3] it is undefined, although it should be populated.

solution seems to be an object with keys, rather than an array. You could do the following
var solution = snap.val();
var array = Object.keys(solution).map(key => ({ ...solution[key], id: key }));
for ....

Related

Re-Map an array of Object based on sort order of a property

Let's see I have a data in following structure
[
{
"Id": "xyz7",
"CurrentRow": 0,
"ReportTime": "2022-07-18T09:00:00+00:00",
"ExitTime": null,
"DateField": "2022-07-18"
},
{
"Id": "xyz8",
"CurrentRow": 1,
"ReportTime": "2022-07-18T08:00:00+00:00",
"ExitTime": null,
"DateField": "2022-07-18"
},
{
"Id": "wxyz0",
"CurrentRow": 0,
"ReportTime": "2022-07-19T00:00:00+00:00",
"ExitTime": null,
"DateField": "2022-07-19"
},
{
"Id": "wxyz1",
"CurrentRow": 1,
"ReportTime": "2022-07-19T00:00:00+00:00",
"ExitTime": null
"DateField": "2022-07-19"
}
]
If I have to say sort the structure based on ReportTime of Date : 2022-07-18, that will change the CurrentRow of entries for DateField 2022-07-18 as
0 to 1 (as it will now belong to 1st Index) and for 2nd entry 1 - 0.
In addition, the CurrentRow of other entries (for other date shall also be adapted if they were same as that of day being sorted.)
In order to achieve this my implementation goes like,
I convert the structure to a two dimensional array based on CurrentRow.
Index in dimension 1, represents the CurrentRow.
The element of array will be an array of specific data entry like [entry_for_date_18,entry_for_date_19] (Kind of spread sheet with date as columns and CurrentRow as rows.
And then in order to sort, I pick all the entries for a particular date, sort it, and collect it with the original CurrentRow. (Pass 1).
Then I go and update the CurrentRow of original array, using the index (pass 2).
e.g pseudo code:
for(let i=0;i<sortedDayArray.length;i++){
findByInOriginalArray(sortedDayArray[i].CurrentRow).updateCurrentRowTo(i)
}
Was wondering if there is a better or more efficient way to do that, using map ?
This is how I got your question: you want to sort your array based on ReportTime, then re-arrange CurrentRow based on its position in DateField and this is the data you are expecting:
[
{
Id: 'xyz8',
CurrentRow: 0,
ReportTime: '2022-07-18T08:00:00+00:00',
ExitTime: null,
DateField: '2022-07-18'
},
{
Id: 'xyz7',
CurrentRow: 1,
ReportTime: '2022-07-18T09:00:00+00:00',
ExitTime: null,
DateField: '2022-07-18'
},
{
Id: 'wxyz0',
CurrentRow: 0,
ReportTime: '2022-07-19T00:00:00+00:00',
ExitTime: null,
DateField: '2022-07-19'
},
{
Id: 'wxyz1',
CurrentRow: 1,
ReportTime: '2022-07-19T00:00:00+00:00',
ExitTime: null,
DateField: '2022-07-19'
}
]
this is the code I came up with:
var tempRow = 0;
var tempDate = ''
YOUR_ARRAY
.sort((a, b) => (a.ReportTime > b.ReportTime) ? 1 : ((b.ReportTime > a.ReportTime) ? -1 : 0))
.forEach((row, i) => {
if (row.DateField != tempDate) {
tempDate = row.DateField
tempRow = 0
}
row.CurrentRow = tempRow
tempRow++
})

how to get object that arepresent in object?

Actually I'm trying to get all the value of object1 and get true if Like object has some id that match with current user id
Array [
Object {
"id": "-MgFbI5wXjtjKln1Wkqe",
"like": Object {
"-MgpHytKWNplejaxtLLF": "-MgpHytKWNplejaxtLLF",
},
"likes_count": 7,
},
Object {
"id": "-MgpHytKWNplejaxtLLF",
"like": Object {
"-MgFbI5wXjtjKln1Wkqe": "aC9dL88GCAXdnGyefY1XDiXd7Iu1",
},
"likes_count": 0,
},
]
Here is my code, arr contains whole object that are given above
const us = arr.map((item) => {
return item.like;
});
const ik = us.includes(uid);
console.log("snap ", ik);
I want given below object that include like variable true if like object have user id otherwise it assign false
Array [
Object {
"id": "-MgFbI5wXjtjKln1Wkqe",
"like":false,
"likes_count": 7,
},
Object {
"id": "-MgpHytKWNplejaxtLLF",
"like":true,
"likes_count": 0,
},
]
const us =Array(); // us is the final table that you need
for(i=0;i<arr.length;i++){
us[i]= {
"id":arr[i].id,
"like": arr[i].like===uid?true:false,
"likes_count": arr[i].likes_count,
}
}
or this :
const us = Array();// us is the final table that you need
arr.forEach((element,index) => us[index] = {
"id":arr[index].id,
"like": arr[index].like===uid?true:false,
"likes_count": arr[index].likes_count,} );

How do I segment this array according to returned key in Vue JavaScript?

I have the following array which contains 132 action_id's:
[ { "id": 1, "project_id": 6, "action_1": 0, "action_2": 0, "action_3": 0, "action_4": 0, "action_5": 0, "action_6": 0, "action_7": 0, "action_8": 0 ..."action_132": 0]
This is returned here:
progress() {
return this.$store.getters['progress/getProgress']
}
The action_ id's are numbered for a particular reason -they all belong to Tasks, of which there are 11.
For instance:
action_1 - action_3 belong to Task 1,
action_4 - action_8 belong to Task 2,
action_9 - action_11 belong to Task 3, and so on...
How can I write a JavaScript function that would segment the actions into Task arrays?
So I would have something like
Task1:
[
action_1,
action_2,
action_3,
]`
`Task2:
[
action_4,
action_5,
action_6,
action_7,
action_8
]`
`Task3:
[
action_9,
action_10,
action_11,
]`...
`Task11:
[
action_128,
action_129,
action_130,
action_131,
action_132
]
I already know which action_id's belong to which Task so in my mind I imagine something like:
Loop through `progress` {
if action_1 to action_3 {
Task1.push
}
if action_4 to action_8 {
Task2.push
}
if action_9 to action_11 {
Task3.push
}
}
What would be the correct syntax to make this happen?
I assume the process is the task object { "id": 1, "project_id": 6, "action_1": 0, "action_2": 0, "action_3": 0, ..."action_132": 0
Object.keys(process).map(key => {
if (key.includes('action')) {
const actionNumber = key.substring(7) // get action number
if (1 <= actionNumber <= 3) {
task1.push(process[key]) // push the value of that action to task
}
... for another eondition
}
})

How to add an object in reducer?

I have a store that looks like this, 3 objects within an array that carry array. How can I add an object in between the first and second object that carry index 1 and 2?
{
object: [
{
"index": 1,
"title": "title",
"caption": "caption",
},
{
"index": 2,
"title": "title",
"caption": "caption",
},
{
"index": 3,
"title": "title",
"caption": "caption",
},
]
}
Would like to have the final output like this after clicking a button that pass in the index value of 1.
{
object: [
{
"index": 1,
"title": "title",
"caption": "caption",
},
{
"index": 2,
"title": "NEW",
"caption": "NEW",
},
{
"index": 3,
"title": "title",
"caption": "caption",
},
{
"index": 4,
"title": "title",
"caption": "caption",
},
]
}
I can use the following codes to change the index value through action, but how to add another new object in between object 1 and object 2, plus changing the index value at the same time?
switch (action.type) {
case ADDCOMPONENT:
return {
...state,
object: state.object.map(component =>
(component.index > action.index ?
{ ...component, index: component.index + 1 } : component)),
};
smth.object.splice(index, 0, item);
And don't keep item index as a string. You can easily get position of item in array, and then add 1 to the value
state.object.splice(component.index, 0, component);
should do the trick
The other answers seem to miss the point that you need to increment the indexes of the other objects in the array. I'd approach it in two steps: first adding the new object with splice, then looping through and incrementing all subsequent indexes.
var index = 1;
state.object.splice(index, 0, new_component); //Insert the new object
//Starting where you inserted, add one to all later components
for (var i = index +1; i < state.object.length; i++) {
state.object[i].index ++;
}
After this state holds the value you want.
However, I'd encourage you to think about if the objects really need to know where they are in the array. In my experience, any code that would need to access the objects would be able to tell where they are in the array.
The shape of your store is created by the combination of all your reducers. The data that you want to update your store with should be created in your application and then sent to your reducer with dispatch(action). The reducer takes the information on the action and updates your state accordingly. If you want to add an object into an array you can use Array.prototype.splice() as follows: myArray.splice( startIndex, 0, itemsToInsert, ... ).
In short, don't add the object in your reducer. Add it to the data you are sending in your action, before you send the action.
If you would like to be able to insert things into an array and not mutate them, you should think about using a function like the one in this snippet:
function nonMutatingArrayInsert( array, index, insert ) {
// return array if index is outside range of array
if ( index < 0 || index > array.length - 1 ) return array;
// ensure insert is array for concat purposes
let _insert = Array.isArray( insert ) ? insert : [ insert ];
// handle 0 index insert
if ( index === 0 ) { return [ ..._insert, ...array ]; }
// handle end of array insert
if ( index === array.length ) { return [ ...array, ..._insert ] }
// handle everyhing else
const before = array.slice( 0, index );
const after = array.slice( index, array.length );
// return new non-mutated array
return [ ...before, ..._insert, ...after ];
}
let myArray = [ "one", "four" ];
let newArray = nonMutatingArrayInsert( myArray, 1, ["two", "three"] );
console.log( "myArray:\n", myArray );
console.log( "newArray:\n", newArray );
All the answers works, however in order to not mutate the array, I have used the following codes instead.
Slice the array before and insert the new object in between.
let newObject = state.portfolio.components.slice(0, action.index);
newObject = newObject.concat(NEWOBJECT);
newObject = newObject.concat(state.portfolio.components.slice(action.index));
for (let i = action.index; i < newComponent.length; i++) {
newComponent[i].index = i + 1;
}
Replace the object with the newObject.
switch (action.type) {
case ADDCOMPONENT:
return {
...state,
object: newObject,
};
EDITED: Used immutability-helper in the end with simpler codes without mutating.
return update(state, {
portfolio: {
object: {
$splice: [
[action.index + 1, 0, action.newObject],
],
},
}
});

Get some values in json array

I have a json that looks like this.
How can I retrieve the information inside the group "demo", without looking into the array like: json['data'][0] I wanted to retrieve the info reading the first value.. "group" and if it matches demo, get all that group info.
{
"filter": "*",
"data": [
{
"group": "asdasd",
"enable": 1,
"timeout": 7,
"otpMode": 0,
"company": "cool",
"signature": "ou yeah",
"supportPage": "",
"newsLanguages": [
0,
0,
0,
0,
0,
0,
0,
0
],
"newsLanguagesTotal": 0
},
{
"group": "demo",
"enable": 1,
"timeout": 7,
"otpMode": 0,
"company": "pppppooo",
"signature": "TTCM",
"supportPage": "http://www.trz<xa",
"newsLanguages": [
0,
0
],
"newsLanguagesTotal": 0
}
]
}
So long I have:
let json = JSON.parse(body);
//console.log(json);
console.log(json['data'][1]);
Which access to "demo"
Process each "data item" and check for the group value. If it matches, then do something.
var json = JSON.parse(jsonStr);
for(var i=0;i<json.data.length;i++){
if(json.data[i].group == "demo"){
var group = json.data[i];
// Process the group info
}
}
I suggest you use the filter()
json.data.filter(function(item){
return item.group === "demo";
});
this will return the objects that have "demo" in the group property
Or if you want to get fancy es6 with it
json.data.filter(item => item.group === "demo");
If the key "group" is missing for any of the records, a simple check (similar to the code provided by #MarkSkayff) will give an error. To fix this, check to see if json["data"][i] exists and check if json["data"[i]["group"] also exists
function json_data(){
var res=[]
for (var i in json["data"]){
if(json["data"][i] && json["data"][i]["group"] === "demo"){ //strict comparison and boolean shortcircuiting
res.push(json["data"][i])
}
}
console.log(res)
}
The result is stored in res
Not enough space here but for more on boolean short circuiting read this explanation of dealing with irregular JSON data

Categories